fix conflict

This commit is contained in:
horike37 2017-08-25 07:05:46 +09:00
commit 388f0e502a
141 changed files with 4631 additions and 2728 deletions

20
.appveyor.yml Normal file
View File

@ -0,0 +1,20 @@
environment:
global:
SLS_IGNORE_WARNING: "*"
matrix:
- NODEJS_VERSION: "4"
- NODEJS_VERSION: "6"
install:
# Get the version of Node.js
- ps: Install-Product node $Env:NODEJS_VERSION
# install modules
- npm install
- node --version
- npm --version
test_script:
- npm test
# Don't actually build.
build: off

View File

@ -2,3 +2,4 @@ coverage
node_modules
tmp
tmpdirs-serverless
lib/plugins/create/templates/**

View File

@ -1,3 +1,28 @@
# 1.20.2 (17.08.2017)
- [Bump event-gateway version to 0.5.15](https://github.com/serverless/serverless/pull/4116)
## Meta
- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.20.1...v1.20.2)
# 1.20.1 (17.08.2017)
- [Rethrow original plugin error in debug mode](https://github.com/serverless/serverless/pull/4091)
- [Add platform gate to serverless run / emit](https://github.com/serverless/serverless/pull/4103)
## Meta
- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.20.0...v1.20.1)
# 1.20.0 (16.08.2017)
- [Add Serverless Run plugin](https://github.com/serverless/serverless/pull/4034)
- [Add Serverless Emit plugin](https://github.com/serverless/serverless/pull/4038)
- [Kubeless template for python and nodejs](https://github.com/serverless/serverless/pull/3970)
- [Improve deprecation hook message](https://github.com/serverless/serverless/pull/4011)
## Meta
- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.19.0...v1.20.0)
# 1.19.0 (02.08.2017)
- [Removed provider name validation](https://github.com/serverless/serverless/pull/3941)
- [Fixed a bug with dev dependencies exclusion](https://github.com/serverless/serverless/pull/3975)
@ -8,7 +33,6 @@
- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.18.1...v1.19.0)
# 1.18.1 (28.07.2017)
- [Fixed a bug with Serverless Variables](https://github.com/serverless/serverless/pull/3996)
- [Fixed a bug with dev dependencies exclusion](https://github.com/serverless/serverless/pull/3975)

View File

@ -6,5 +6,8 @@ RUN curl -o- -L https://yarnpkg.com/install.sh | bash
# install python tooling
RUN apt-get update -y && apt-get install -y python-dev python-pip && pip install --upgrade pip
# install other utils
RUN apt-get update -y && apt-get install -y screen
# install aws-cli
RUN pip install awscli

226
README.md
View File

@ -1,4 +1,4 @@
[![Serverless Application Framework AWS Lambda API Gateway](https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/serverless_framework_v1_d.gif)](http://serverless.com)
[![Serverless Application Framework AWS Lambda API Gateway](./assets/framework_repo.png)](http://serverless.com)
[![serverless](http://public.serverless.com/badges/v3.svg)](http://www.serverless.com)
[![Build Status](https://travis-ci.org/serverless/serverless.svg?branch=master)](https://travis-ci.org/serverless/serverless)
@ -152,74 +152,74 @@ This table is generated from https://github.com/serverless/plugins/blob/master/p
-->
| Plugin | Author |
|:-------|:------:|
| **[API GW binary support](https://github.com/maciejtreder/serverless-apigw-binary)** <br/> Serverless plugin to enable binary support in AWS API Gateway. | [Maciej Treder](https://github.com/maciejtreder) |
| **[Raml Serverless](https://github.com/andrewcurioso/raml-serverless)** <br/> Serverless plugin to work with RAML API spec documents | [andrewcurioso](http://github.com/andrewcurioso) |
| **[Serverless Alexa Plugin](https://github.com/rajington/serverless-alexa-plugin)** <br/> Serverless plugin to support Alexa Lambda events | [rajington](http://github.com/rajington) |
| **[Serverless Api Stage](https://github.com/leftclickben/serverless-api-stage)** <br/> Serverless API Stage plugin, enables stage variables and logging for AWS API Gateway. | [leftclickben](http://github.com/leftclickben) |
| **[Serverless Apig S3](https://github.com/sdd/serverless-apig-s3)** <br/> Serve static front-end content from S3 via the API Gatewy and deploy client bundle to S3. | [sdd](http://github.com/sdd) |
| **[Serverless Aws Alias](https://github.com/HyperBrain/serverless-aws-alias)** <br/> This plugin enables use of AWS aliases on Lambda functions. | [HyperBrain](http://github.com/HyperBrain) |
| **[Serverless Aws Documentation](https://github.com/9cookies/serverless-aws-documentation)** <br/> Serverless plugin to add documentation and models to the serverless generated API Gateway | [9cookies](http://github.com/9cookies) |
| **[Serverless Build Plugin](https://github.com/nfour/serverless-build-plugin)** <br/> A Node.js focused build plugin for serverless. | [nfour](http://github.com/nfour) |
| **[Serverless Cljs Plugin](https://github.com/nervous-systems/serverless-cljs-plugin)** <br/> Enables Clojurescript as an implementation language for Lambda handlers | [nervous-systems](http://github.com/nervous-systems) |
| **[Serverless Coffeescript](https://github.com/duanefields/serverless-coffeescript)** <br/> A Serverless plugin to compile your CoffeeScript into JavaScript at deployment | [duanefields](http://github.com/duanefields) |
| **[Serverless Command Line Event Args](https://github.com/horike37/serverless-command-line-event-args)** <br/> This module is Serverless Framework plugin. Event JSON passes to your Lambda function in commandline. | [horike37](http://github.com/horike37) |
| **[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 Dir Config Plugin](https://github.com/economysizegeek/serverless-dir-config-plugin)** <br/> EXPERIMENTAL - Serverless plugin to load function and resource definitions from a directory. | [economysizegeek](http://github.com/economysizegeek) |
| **[Serverless Dotenv](https://github.com/Jimdo/serverless-dotenv)** <br/> Fetch environment variables and write it to a .env file | [Jimdo](http://github.com/Jimdo) |
| **[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 Dynalite](https://github.com/sdd/serverless-dynalite)** <br/> Run dynalite locally (no JVM, all JS) to simulate DynamoDB. Watch serverless.yml for table config updates. | [sdd](http://github.com/sdd) |
| **[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 Dynamodb Ttl](https://github.com/Jimdo/serverless-dynamodb-ttl)** <br/> Configure DynamoDB TTL in serverless.yml (until CloudFormation supports this). | [Jimdo](http://github.com/Jimdo) |
| **[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 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 Export Env](https://github.com/arabold/serverless-export-env)** <br/> Export environment variables into a .env file with automatic AWS CloudFormation reference resolution. | [arabold](http://github.com/arabold) |
| **[Serverless Hooks Plugin](https://github.com/uswitch/serverless-hooks-plugin)** <br/> Run arbitrary commands on any lifecycle event in serverless | [uswitch](http://github.com/uswitch) |
| **[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) |
| **[Serverless Offline](https://github.com/dherault/serverless-offline)** <br/> Emulate AWS λ and API Gateway locally when developing your Serverless project | [dherault](http://github.com/dherault) |
| **[Serverless Offline Scheduler](https://github.com/ajmath/serverless-offline-scheduler)** <br/> Runs scheduled functions offline while integrating with serverless-offline | [ajmath](http://github.com/ajmath) |
| **[Serverless Package Python Functions](https://github.com/ubaniabalogun/serverless-package-python-functions)** <br/> Packaging Python Lambda functions with only the dependencies/requirements they need. | [ubaniabalogun](http://github.com/ubaniabalogun) |
| **[Serverless Parameters](https://github.com/svdgraaf/serverless-parameters)** <br/> Add parameters to the generated cloudformation templates | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Plugin Aws Alerts](https://github.com/ACloudGuru/serverless-plugin-aws-alerts)** <br/> A Serverless plugin to easily add CloudWatch alarms to functions | [ACloudGuru](http://github.com/ACloudGuru) |
| **[Serverless Plugin Bind Deployment Id](https://github.com/jacob-meacham/serverless-plugin-bind-deployment-id)** <br/> A Serverless plugin to bind the randomly generated deployment resource to your custom resources | [jacob-meacham](http://github.com/jacob-meacham) |
| **[Serverless Plugin Browserify](https://github.com/doapp-ryanp/serverless-plugin-browserify)** <br/> Speed up your node based lambda's | [doapp-ryanp](http://github.com/doapp-ryanp) |
| **[Serverless Plugin Cfauthorizer](https://github.com/SC5/serverless-plugin-cfauthorizer)** <br/> This plugin allows you to define your own API Gateway Authorizers as the Serverless CloudFormation resources and apply them to HTTP endpoints. | [SC5](http://github.com/SC5) |
| **[Serverless Plugin Cloudwatch Sumologic](https://github.com/ACloudGuru/serverless-plugin-cloudwatch-sumologic)** <br/> Plugin which auto-subscribes a log delivery lambda function to lambda log groups created by serverless | [ACloudGuru](http://github.com/ACloudGuru) |
| **[Serverless Plugin Diff](https://github.com/nicka/serverless-plugin-diff)** <br/> Compares your local AWS CloudFormation templates against deployed ones. | [nicka](http://github.com/nicka) |
| **[Serverless Plugin Encode Env Var Objects](https://github.com/yonomi/serverless-plugin-encode-env-var-objects)** <br/> Serverless plugin to encode any environment variable objects. | [yonomi](http://github.com/yonomi) |
| **[Serverless Plugin External Sns Events](https://github.com/silvermine/serverless-plugin-external-sns-events)** <br/> Add ability for functions to use existing or external SNS topics as an event source | [silvermine](http://github.com/silvermine) |
| **[Serverless Plugin Git Variables](https://github.com/jacob-meacham/serverless-plugin-git-variables)** <br/> A Serverless plugin to expose git variables (branch name, HEAD description, full commit hash) to your serverless services | [jacob-meacham](http://github.com/jacob-meacham) |
| **[Serverless Plugin Graphiql](https://github.com/bencooling/serverless-plugin-graphiql)** <br/> A Serverless plugin to run a local http server for graphiql and your graphql handler | [bencooling](http://github.com/bencooling) |
| **[Serverless Plugin Include Dependencies](https://github.com/dougmoscrop/serverless-plugin-include-dependencies)** <br/> This is a Serverless plugin that should make your deployed functions smaller. | [dougmoscrop](http://github.com/dougmoscrop) |
| **[Serverless Plugin Iopipe](https://github.com/iopipe/serverless-plugin-iopipe)** <br/> See inside your Lambda functions with high fidelity metrics and monitoring. | [iopipe](http://github.com/iopipe) |
| **[Serverless Plugin Lambda Dead Letter](https://github.com/gmetzker/serverless-plugin-lambda-dead-letter)** <br/> A Serverless plugin that can configure a lambda with a dead letter queue or topic | [gmetzker](http://github.com/gmetzker) |
| **[Serverless Plugin Multiple Responses](https://github.com/silvermine/serverless-plugin-multiple-responses)** <br/> Enable multiple content-types for Response template | [silvermine](http://github.com/silvermine) |
| **[Serverless Plugin Optimize](https://github.com/FidelLimited/serverless-plugin-optimize)** <br/> Bundle with Browserify, transpile with Babel to ES5 and minify with Uglify your Serverless functions. | [FidelLimited](http://github.com/FidelLimited) |
| **[Serverless Plugin Package Dotenv File](https://github.com/ACloudGuru/serverless-plugin-package-dotenv-file)** <br/> A Serverless plugin to copy a .env file into the serverless package | [ACloudGuru](http://github.com/ACloudGuru) |
| **[Serverless Plugin Scripts](https://github.com/mvila/serverless-plugin-scripts)** <br/> Add scripting capabilities to the Serverless Framework | [mvila](http://github.com/mvila) |
| **[Serverless Plugin Select](https://github.com/FidelLimited/serverless-plugin-select)** <br/> Select which functions are to be deployed based on region and stage. | [FidelLimited](http://github.com/FidelLimited) |
| **[Serverless Plugin Simulate](https://github.com/gertjvr/serverless-plugin-simulate)** <br/> Simulate AWS Lambda and API Gateway locally using Docker | [gertjvr](http://github.com/gertjvr) |
| **[Serverless Plugin Stack Outputs](https://github.com/svdgraaf/serverless-plugin-stack-outputs)** <br/> Displays stack outputs for your serverless stacks when `sls info` is ran | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Plugin Stage Variables](https://github.com/svdgraaf/serverless-plugin-stage-variables)** <br/> Add stage variables for Serverless 1.x to ApiGateway, so you can use variables in your Lambda's | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Plugin Subscription Filter](https://github.com/tsub/serverless-plugin-subscription-filter)** <br/> A serverless plugin to register AWS CloudWatchLogs subscription filter | [tsub](http://github.com/tsub) |
| **[Serverless Plugin Typescript](https://github.com/graphcool/serverless-plugin-typescript)** <br/> Serverless plugin for zero-config Typescript support. | [graphcool](http://github.com/graphcool) |
| **[Serverless Plugin Warmup](https://github.com/FidelLimited/serverless-plugin-warmup)** <br/> Keep your lambdas warm during Winter. | [FidelLimited](http://github.com/FidelLimited) |
| **[Serverless Plugin Webpack](https://github.com/goldwasserexchange/serverless-plugin-webpack)** <br/> A serverless plugin to automatically bundle your functions individually with webpack | [goldwasserexchange](http://github.com/goldwasserexchange) |
| **[Serverless Plugin Write Env Vars](https://github.com/silvermine/serverless-plugin-write-env-vars)** <br/> Write environment variables out to a file that is compatible with dotenv | [silvermine](http://github.com/silvermine) |
| **[Serverless Prune Plugin](https://github.com/claygregory/serverless-prune-plugin)** <br/> Deletes old versions of functions from AWS, preserving recent and aliased versions | [claygregory](http://github.com/claygregory) |
| **[Serverless Pseudo Parameters](https://github.com/svdgraaf/serverless-pseudo-parameters)** <br/> Use ${AWS::AccountId} and other cloudformation pseudo parameters in your serverless.yml values | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Python Individually](https://github.com/cfchou/serverless-python-individually)** <br/> A serverless framework plugin to install multiple lambda functions written in python | [cfchou](http://github.com/cfchou) |
| **[Serverless Python Requirements](https://github.com/UnitedIncome/serverless-python-requirements)** <br/> Serverless plugin to bundle Python packages | [UnitedIncome](http://github.com/UnitedIncome) |
| **[Serverless Resources Env](https://github.com/rurri/serverless-resources-env)** <br/> After Deploy, this plugin fetches cloudformation resource identifiers and sets them on AWS lambdas, and creates local .<state>-env file | [rurri](http://github.com/rurri) |
| **[Serverless Run Function Plugin](https://github.com/lithin/serverless-run-function-plugin)** <br/> Run serverless function locally | [lithin](http://github.com/lithin) |
| **[Serverless Sam](https://github.com/SAPessi/serverless-sam)** <br/> Exports an AWS SAM template for a service created with the Serverless Framework. | [SAPessi](http://github.com/SAPessi) |
| **[Serverless Scriptable Plugin](https://github.com/weixu365/serverless-scriptable-plugin)** <br/> Customize Serverless behavior without writing a plugin. | [weixu365](http://github.com/weixu365) |
| **[Serverless Sqs Alarms Plugin](https://github.com/sbstjn/serverless-sqs-alarms-plugin)** <br/> Wrapper to setup CloudWatch Alarms on SQS queue length | [sbstjn](http://github.com/sbstjn) |
| **[Serverless Sqs Fifo](https://github.com/vortarian/serverless-sqs-fifo)** <br/> A serverless plugin to handle creation of sqs fifo queue's in aws (stop-gap) | [vortarian](http://github.com/vortarian) |
| **[Serverless Step Functions](https://github.com/horike37/serverless-step-functions)** <br/> AWS Step Functions with Serverless Framework. | [horike37](http://github.com/horike37) |
| **[Serverless Subscription Filter](https://github.com/blackevil245/serverless-subscription-filter)** <br/> Serverless plugin to register subscription filter for Lambda logs. Register and pipe the logs of one lambda to another to process. | [blackevil245](http://github.com/blackevil245) |
| **[Serverless Vpc Discovery](https://github.com/amplify-education/serverless-vpc-discovery)** <br/> Serverless plugin for discovering VPC / Subnet / Security Group configuration by name. | [amplify-education](http://github.com/amplify-education) |
| **[Serverless Webpack](https://github.com/elastic-coders/serverless-webpack)** <br/> Serverless plugin to bundle your lambdas with Webpack | [elastic-coders](http://github.com/elastic-coders) |
| **[API GW binary support](https://github.com/maciejtreder/serverless-apigw-binary)** <br/> Serverless plugin to enable binary support in AWS API Gateway. | [Maciej Treder](https://github.com/maciejtreder) |
| **[Raml Serverless](https://github.com/andrewcurioso/raml-serverless)** <br/> Serverless plugin to work with RAML API spec documents | [andrewcurioso](http://github.com/andrewcurioso) |
| **[Serverless Alexa Plugin](https://github.com/rajington/serverless-alexa-plugin)** <br/> Serverless plugin to support Alexa Lambda events | [rajington](http://github.com/rajington) |
| **[Serverless Api Stage](https://github.com/leftclickben/serverless-api-stage)** <br/> Serverless API Stage plugin, enables stage variables and logging for AWS API Gateway. | [leftclickben](http://github.com/leftclickben) |
| **[Serverless Apig S3](https://github.com/sdd/serverless-apig-s3)** <br/> Serve static front-end content from S3 via the API Gatewy and deploy client bundle to S3. | [sdd](http://github.com/sdd) |
| **[Serverless Aws Alias](https://github.com/HyperBrain/serverless-aws-alias)** <br/> This plugin enables use of AWS aliases on Lambda functions. | [HyperBrain](http://github.com/HyperBrain) |
| **[Serverless Aws Documentation](https://github.com/9cookies/serverless-aws-documentation)** <br/> Serverless plugin to add documentation and models to the serverless generated API Gateway | [9cookies](http://github.com/9cookies) |
| **[Serverless Build Plugin](https://github.com/nfour/serverless-build-plugin)** <br/> A Node.js focused build plugin for serverless. | [nfour](http://github.com/nfour) |
| **[Serverless Cljs Plugin](https://github.com/nervous-systems/serverless-cljs-plugin)** <br/> Enables Clojurescript as an implementation language for Lambda handlers | [nervous-systems](http://github.com/nervous-systems) |
| **[Serverless Coffeescript](https://github.com/duanefields/serverless-coffeescript)** <br/> A Serverless plugin to compile your CoffeeScript into JavaScript at deployment | [duanefields](http://github.com/duanefields) |
| **[Serverless Command Line Event Args](https://github.com/horike37/serverless-command-line-event-args)** <br/> This module is Serverless Framework plugin. Event JSON passes to your Lambda function in commandline. | [horike37](http://github.com/horike37) |
| **[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 Dir Config Plugin](https://github.com/economysizegeek/serverless-dir-config-plugin)** <br/> EXPERIMENTAL - Serverless plugin to load function and resource definitions from a directory. | [economysizegeek](http://github.com/economysizegeek) |
| **[Serverless Dotenv](https://github.com/Jimdo/serverless-dotenv)** <br/> Fetch environment variables and write it to a .env file | [Jimdo](http://github.com/Jimdo) |
| **[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 Dynalite](https://github.com/sdd/serverless-dynalite)** <br/> Run dynalite locally (no JVM, all JS) to simulate DynamoDB. Watch serverless.yml for table config updates. | [sdd](http://github.com/sdd) |
| **[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 Dynamodb Ttl](https://github.com/Jimdo/serverless-dynamodb-ttl)** <br/> Configure DynamoDB TTL in serverless.yml (until CloudFormation supports this). | [Jimdo](http://github.com/Jimdo) |
| **[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 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 Export Env](https://github.com/arabold/serverless-export-env)** <br/> Export environment variables into a .env file with automatic AWS CloudFormation reference resolution. | [arabold](http://github.com/arabold) |
| **[Serverless Hooks Plugin](https://github.com/uswitch/serverless-hooks-plugin)** <br/> Run arbitrary commands on any lifecycle event in serverless | [uswitch](http://github.com/uswitch) |
| **[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) |
| **[Serverless Offline](https://github.com/dherault/serverless-offline)** <br/> Emulate AWS λ and API Gateway locally when developing your Serverless project | [dherault](http://github.com/dherault) |
| **[Serverless Offline Scheduler](https://github.com/ajmath/serverless-offline-scheduler)** <br/> Runs scheduled functions offline while integrating with serverless-offline | [ajmath](http://github.com/ajmath) |
| **[Serverless Package Python Functions](https://github.com/ubaniabalogun/serverless-package-python-functions)** <br/> Packaging Python Lambda functions with only the dependencies/requirements they need. | [ubaniabalogun](http://github.com/ubaniabalogun) |
| **[Serverless Parameters](https://github.com/svdgraaf/serverless-parameters)** <br/> Add parameters to the generated cloudformation templates | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Plugin Aws Alerts](https://github.com/ACloudGuru/serverless-plugin-aws-alerts)** <br/> A Serverless plugin to easily add CloudWatch alarms to functions | [ACloudGuru](http://github.com/ACloudGuru) |
| **[Serverless Plugin Bind Deployment Id](https://github.com/jacob-meacham/serverless-plugin-bind-deployment-id)** <br/> A Serverless plugin to bind the randomly generated deployment resource to your custom resources | [jacob-meacham](http://github.com/jacob-meacham) |
| **[Serverless Plugin Browserify](https://github.com/doapp-ryanp/serverless-plugin-browserify)** <br/> Speed up your node based lambda's | [doapp-ryanp](http://github.com/doapp-ryanp) |
| **[Serverless Plugin Cfauthorizer](https://github.com/SC5/serverless-plugin-cfauthorizer)** <br/> This plugin allows you to define your own API Gateway Authorizers as the Serverless CloudFormation resources and apply them to HTTP endpoints. | [SC5](http://github.com/SC5) |
| **[Serverless Plugin Cloudwatch Sumologic](https://github.com/ACloudGuru/serverless-plugin-cloudwatch-sumologic)** <br/> Plugin which auto-subscribes a log delivery lambda function to lambda log groups created by serverless | [ACloudGuru](http://github.com/ACloudGuru) |
| **[Serverless Plugin Diff](https://github.com/nicka/serverless-plugin-diff)** <br/> Compares your local AWS CloudFormation templates against deployed ones. | [nicka](http://github.com/nicka) |
| **[Serverless Plugin Encode Env Var Objects](https://github.com/yonomi/serverless-plugin-encode-env-var-objects)** <br/> Serverless plugin to encode any environment variable objects. | [yonomi](http://github.com/yonomi) |
| **[Serverless Plugin External Sns Events](https://github.com/silvermine/serverless-plugin-external-sns-events)** <br/> Add ability for functions to use existing or external SNS topics as an event source | [silvermine](http://github.com/silvermine) |
| **[Serverless Plugin Git Variables](https://github.com/jacob-meacham/serverless-plugin-git-variables)** <br/> A Serverless plugin to expose git variables (branch name, HEAD description, full commit hash) to your serverless services | [jacob-meacham](http://github.com/jacob-meacham) |
| **[Serverless Plugin Graphiql](https://github.com/bencooling/serverless-plugin-graphiql)** <br/> A Serverless plugin to run a local http server for graphiql and your graphql handler | [bencooling](http://github.com/bencooling) |
| **[Serverless Plugin Include Dependencies](https://github.com/dougmoscrop/serverless-plugin-include-dependencies)** <br/> This is a Serverless plugin that should make your deployed functions smaller. | [dougmoscrop](http://github.com/dougmoscrop) |
| **[Serverless Plugin Iopipe](https://github.com/iopipe/serverless-plugin-iopipe)** <br/> See inside your Lambda functions with high fidelity metrics and monitoring. | [iopipe](http://github.com/iopipe) |
| **[Serverless Plugin Lambda Dead Letter](https://github.com/gmetzker/serverless-plugin-lambda-dead-letter)** <br/> A Serverless plugin that can configure a lambda with a dead letter queue or topic | [gmetzker](http://github.com/gmetzker) |
| **[Serverless Plugin Multiple Responses](https://github.com/silvermine/serverless-plugin-multiple-responses)** <br/> Enable multiple content-types for Response template | [silvermine](http://github.com/silvermine) |
| **[Serverless Plugin Optimize](https://github.com/FidelLimited/serverless-plugin-optimize)** <br/> Bundle with Browserify, transpile with Babel to ES5 and minify with Uglify your Serverless functions. | [FidelLimited](http://github.com/FidelLimited) |
| **[Serverless Plugin Package Dotenv File](https://github.com/ACloudGuru/serverless-plugin-package-dotenv-file)** <br/> A Serverless plugin to copy a .env file into the serverless package | [ACloudGuru](http://github.com/ACloudGuru) |
| **[Serverless Plugin Scripts](https://github.com/mvila/serverless-plugin-scripts)** <br/> Add scripting capabilities to the Serverless Framework | [mvila](http://github.com/mvila) |
| **[Serverless Plugin Select](https://github.com/FidelLimited/serverless-plugin-select)** <br/> Select which functions are to be deployed based on region and stage. | [FidelLimited](http://github.com/FidelLimited) |
| **[Serverless Plugin Simulate](https://github.com/gertjvr/serverless-plugin-simulate)** <br/> Simulate AWS Lambda and API Gateway locally using Docker | [gertjvr](http://github.com/gertjvr) |
| **[Serverless Plugin Stack Outputs](https://github.com/svdgraaf/serverless-plugin-stack-outputs)** <br/> Displays stack outputs for your serverless stacks when `sls info` is ran | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Plugin Stage Variables](https://github.com/svdgraaf/serverless-plugin-stage-variables)** <br/> Add stage variables for Serverless 1.x to ApiGateway, so you can use variables in your Lambda's | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Plugin Subscription Filter](https://github.com/tsub/serverless-plugin-subscription-filter)** <br/> A serverless plugin to register AWS CloudWatchLogs subscription filter | [tsub](http://github.com/tsub) |
| **[Serverless Plugin Typescript](https://github.com/graphcool/serverless-plugin-typescript)** <br/> Serverless plugin for zero-config Typescript support. | [graphcool](http://github.com/graphcool) |
| **[Serverless Plugin Warmup](https://github.com/FidelLimited/serverless-plugin-warmup)** <br/> Keep your lambdas warm during Winter. | [FidelLimited](http://github.com/FidelLimited) |
| **[Serverless Plugin Webpack](https://github.com/goldwasserexchange/serverless-plugin-webpack)** <br/> A serverless plugin to automatically bundle your functions individually with webpack | [goldwasserexchange](http://github.com/goldwasserexchange) |
| **[Serverless Plugin Write Env Vars](https://github.com/silvermine/serverless-plugin-write-env-vars)** <br/> Write environment variables out to a file that is compatible with dotenv | [silvermine](http://github.com/silvermine) |
| **[Serverless Prune Plugin](https://github.com/claygregory/serverless-prune-plugin)** <br/> Deletes old versions of functions from AWS, preserving recent and aliased versions | [claygregory](http://github.com/claygregory) |
| **[Serverless Pseudo Parameters](https://github.com/svdgraaf/serverless-pseudo-parameters)** <br/> Use ${AWS::AccountId} and other cloudformation pseudo parameters in your serverless.yml values | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Python Individually](https://github.com/cfchou/serverless-python-individually)** <br/> A serverless framework plugin to install multiple lambda functions written in python | [cfchou](http://github.com/cfchou) |
| **[Serverless Python Requirements](https://github.com/UnitedIncome/serverless-python-requirements)** <br/> Serverless plugin to bundle Python packages | [UnitedIncome](http://github.com/UnitedIncome) |
| **[Serverless Resources Env](https://github.com/rurri/serverless-resources-env)** <br/> After Deploy, this plugin fetches cloudformation resource identifiers and sets them on AWS lambdas, and creates local .<state>-env file | [rurri](http://github.com/rurri) |
| **[Serverless Run Function Plugin](https://github.com/lithin/serverless-run-function-plugin)** <br/> Run serverless function locally | [lithin](http://github.com/lithin) |
| **[Serverless Sam](https://github.com/SAPessi/serverless-sam)** <br/> Exports an AWS SAM template for a service created with the Serverless Framework. | [SAPessi](http://github.com/SAPessi) |
| **[Serverless Scriptable Plugin](https://github.com/weixu365/serverless-scriptable-plugin)** <br/> Customize Serverless behavior without writing a plugin. | [weixu365](http://github.com/weixu365) |
| **[Serverless Sqs Alarms Plugin](https://github.com/sbstjn/serverless-sqs-alarms-plugin)** <br/> Wrapper to setup CloudWatch Alarms on SQS queue length | [sbstjn](http://github.com/sbstjn) |
| **[Serverless Sqs Fifo](https://github.com/vortarian/serverless-sqs-fifo)** <br/> A serverless plugin to handle creation of sqs fifo queue's in aws (stop-gap) | [vortarian](http://github.com/vortarian) |
| **[Serverless Step Functions](https://github.com/horike37/serverless-step-functions)** <br/> AWS Step Functions with Serverless Framework. | [horike37](http://github.com/horike37) |
| **[Serverless Subscription Filter](https://github.com/blackevil245/serverless-subscription-filter)** <br/> Serverless plugin to register subscription filter for Lambda logs. Register and pipe the logs of one lambda to another to process. | [blackevil245](http://github.com/blackevil245) |
| **[Serverless Vpc Discovery](https://github.com/amplify-education/serverless-vpc-discovery)** <br/> Serverless plugin for discovering VPC / Subnet / Security Group configuration by name. | [amplify-education](http://github.com/amplify-education) |
| **[Serverless Webpack](https://github.com/elastic-coders/serverless-webpack)** <br/> Serverless plugin to bundle your lambdas with Webpack | [elastic-coders](http://github.com/elastic-coders) |
| **[Serverless Wsgi](https://github.com/logandk/serverless-wsgi)** <br/> Serverless plugin to deploy WSGI applications (Flask/Django/Pyramid etc.) and bundle Python packages | [logandk](http://github.com/logandk) |
<!-- AUTO-GENERATED-CONTENT:END This table is generated from https://github.com/serverless/plugins/blob/master/plugins.json please make additions there -->
@ -230,50 +230,50 @@ This table is generated from https://github.com/serverless/examples/blob/master/
-->
| Project Name | Author |
|:-------------|:------:|
| **[Serverless Graphql Api](https://github.com/boazdejong/serverless-graphql-api)** <br/> Serverless GraphQL API using Lambda and DynamoDB | [boazdejong](http://github.com/boazdejong) |
| **[Serverless Screenshot](https://github.com/svdgraaf/serverless-screenshot)** <br/> Serverless Screenshot Service using PhantomJS | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Postgraphql](https://github.com/rentrop/serverless-postgraphql)** <br/> GraphQL endpoint for PostgreSQL using postgraphql | [rentrop](http://github.com/rentrop) |
| **[Serverless Messenger Boilerplate](https://github.com/SC5/serverless-messenger-boilerplate)** <br/> Serverless messenger bot boilerplate | [SC5](http://github.com/SC5) |
| **[Serverless Npm Registry](https://github.com/craftship/yith)** <br/> Serverless private npm registry, proxy and cache. | [craftship](http://github.com/craftship) |
| **[Serverless Pokego](https://github.com/jch254/pokego-serverless)** <br/> Serverless-powered API to fetch nearby Pokemon Go data | [jch254](http://github.com/jch254) |
| **[Serverless Weekly2pocket App](https://github.com/s0enke/weekly2pocket)** <br/> Serverless-powered API for sending posts to pocket app | [s0enke](http://github.com/s0enke) |
| **[Serverless Facebook Quotebot](https://github.com/pmuens/quotebot)** <br/> 100% Serverless Facebook messenger chatbot which will respond with inspiring quotes | [pmuens](http://github.com/pmuens) |
| **[Serverless Slack Trevorbot](https://github.com/conveyal/trevorbot)** <br/> Slack bot for info on where in the world is Trevor Gerhardt? | [conveyal](http://github.com/conveyal) |
| **[Serverless Garden Aid](https://github.com/garden-aid/web-bff)** <br/> IoT Garden Aid Backend | [garden-aid](http://github.com/garden-aid) |
| **[Serverless React Boilerplate](https://github.com/99xt/serverless-react-boilerplate)** <br/> A serverless react boilerplate for offline development | [99xt](http://github.com/99xt) |
| **[Serverless Delivery Framework](https://github.com/99xt/serverless-delivery-framework)** <br/> This is a boilerplate for version release pipeline with serverless framework | [99xt](http://github.com/99xt) |
| **[Serverless Mailgun Slack](https://github.com/Marcus-L/serverless-mailgun-slack)** <br/> A Serverless function for posting to a Slack Webhook in response to a Mailgun route | [Marcus-L](http://github.com/Marcus-L) |
| **[Pfs Email Serverless](https://github.com/SCPR/pfs-email-serverless)** <br/> This is a lambda function created by the serverless framework. It searches through members in our mongodb who have not been sent emails and sends them an email with their custom token to unlock the pledge free stream. It then marks those members off as already receiving the email. | [SCPR](http://github.com/SCPR) |
| **[Plaid Cashburndown Service](https://github.com/cplee/cashburndown-service)** <br/> Service for calculating cash burndown with plaid. Frontend code can be found here: https://github.com/cplee/cashburndown-site | [cplee](http://github.com/cplee) |
| **[Cordis Serverless](https://github.com/marzeelabs/cordis-serverless)** <br/> A serverless API for EU Cordis data | [marzeelabs](http://github.com/marzeelabs) |
| **[Serverless Newsletter Signup](https://github.com/ivanderbu2/serverless-newsletter-signup)** <br/> Saves user details into DynamoDB table. Required values are email, first_name and last_name. | [ivanderbu2](http://github.com/ivanderbu2) |
| **[Serverless Slack Cron](https://github.com/ivanderbu2/serverless-slack-cron)** <br/> Lambda function which sends messages to Slack channel in regular intervals via cron trigger. | [ivanderbu2](http://github.com/ivanderbu2) |
| **[Giphy Bot](https://github.com/tywong/lambda-workshop-2016/tree/master/giphy-bot)** <br/> giphy-bot for Facebook chat | [tywong](http://github.com/tywong) |
| **[Jwt Lambda Python](https://github.com/mikaelmork/jwt-auth.serverless)** <br/> Minimal proof-of-concept implementation of JWT with Serverless / AWS Lambda | [mikaelmork](http://github.com/mikaelmork) |
| **[Sls Access Counter](https://github.com/takahashim/sls-access-counter)** <br/> Site visitor counter | [takahashim](http://github.com/takahashim) |
| **[Sls Form Mail](https://github.com/takahashim/sls-form-mail)** <br/> Send SNS email from form data | [takahashim](http://github.com/takahashim) |
| **[Serverless Python Sample](https://github.com/bennybauer/serverless-python-sample)** <br/> A simple serverless python sample with REST API endpoints and dependencies | [bennybauer](http://github.com/bennybauer) |
| **[Serverless Msg Gateway](https://github.com/yonahforst/msg-gateway)** <br/> A messaging aggregator for kik, skype, twilio, telegram, & messenger. Send and receive messages in a standard format. | [yonahforst](http://github.com/yonahforst) |
| **[Serverless Aws Rekognition Finpics](https://github.com/rgfindl/finpics)** <br/> Use AWS Rekognition to provide a faces search of finpics.com | [rgfindl](http://github.com/rgfindl) |
| **[Serverless Slack Emojibot](https://github.com/markhobson/emojibot)** <br/> Serverless slack bot for emoji | [markhobson](http://github.com/markhobson) |
| **[Keboola Developer Portal](https://github.com/keboola/developer-portal)** <br/> Keboola developer portal built with Serverless | [keboola](http://github.com/keboola) |
| **[Serverless Cloudwatch Rds Custom Metrics](https://github.com/AndrewFarley/serverless-cloudwatch-rds-custom-metrics)** <br/> A NodeJS-based MySQL RDS Data Collection script to push Custom Metrics to Cloudwatch with Serverless | [AndrewFarley](http://github.com/AndrewFarley) |
| **[Jrestless Examples](https://github.com/bbilger/jrestless-examples)** <br/> [JRestless](https://github.com/bbilger/jrestless) (Java / JAX-RS) examples for [API Gateway Functions](https://github.com/bbilger/jrestless-examples/tree/master/aws/gateway) ([plain JAX-RS](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-showcase), [Spring](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-spring), [binary data requests/responses](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-binary), [custom authorizers](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-custom-authorizer) and [Cognito User Pool authorizers](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-cognito-authorizer)), [SNS Functions](https://github.com/bbilger/jrestless-examples/blob/master/aws/sns/aws-sns-usage-example) (asynchronous communication between functions) and [Service Functions](https://github.com/bbilger/jrestless-examples/blob/master/aws/service/aws-service-usage-example) (synchronous HTTP-like communication between functions - transparent through Feign) | [bbilger](http://github.com/bbilger) |
| **[Sc5 Serverless Boilerplate](https://github.com/SC5/sc5-serverless-boilerplate)** <br/> A boilerplate that contains setup for test-driven development | [SC5](http://github.com/SC5) |
| **[Serverless Blog To Podcast](https://github.com/SC5/serverless-blog-to-podcast)** <br/> Service that reads RSS feed and converts the entries to a podcast feed and audio files using Amazon Polly | [SC5](http://github.com/SC5) |
| **[Offset Trump](https://github.com/FLGMwt/offset-trump)** <br/> Single page app using Serverless (C# runtime) and S3 site hosting. Pledge to do a good thing for the next four years to offset the potential negative effects of the US Presidency | [FLGMwt](http://github.com/FLGMwt) |
| **[Serverless Url Shortener](https://github.com/aletheia/serverless-url-shortener)** <br/> A simple url-shortener, using Serverless framework | [aletheia](http://github.com/aletheia) |
| **[Serverless Html Pdf](https://github.com/calvintychan/serverless-html-pdf)** <br/> Service that convert HTML to PDF using PhantomJS's rasterize example. | [calvintychan](http://github.com/calvintychan) |
| **[Serverless Examples Cached Rds Ws](https://github.com/mugglmenzel/serverless-examples-cached-rds-ws)** <br/> A serverless framework example project that uses API Gateway, ElastiCache, and RDS PostgreSQL. | [mugglmenzel](http://github.com/mugglmenzel) |
| **[Bittman](https://github.com/rhlsthrm/bittman)** <br/> A serverless project that follows a stock trading algorithm and uses scheduled functions to save data to DynamoDB and send emails through Mailgun. | [rhlsthrm](http://github.com/rhlsthrm) |
| **[Adoptable Pet Bot](https://github.com/lynnaloo/adoptable-pet-bot)** <br/> Tweets adoptable pets using Serverless (Node.js) and AWS Lambda | [lynnaloo](http://github.com/lynnaloo) |
| **[Owntracks Serverless](https://github.com/dschep/owntracks-serverless)** <br/> A serverless implementation of the OwnTracks HTTP backend | [dschep](http://github.com/dschep) |
| **[Serverless Modern Koa](https://github.com/barczaG/serverless-modern-koa)** <br/> Serverless modern koa starter kit | [barczaG](http://github.com/barczaG) |
| **[Serverless Reactjs Universal Rendering Boilerplate](https://github.com/TylorShin/react-universal-in-serverless)** <br/> ReactJS web app Starter kit does universal (isomorphic) rendering with Serverless | [TylorShin](http://github.com/TylorShin) |
| **[Open Bot](https://github.com/open-bot/open-bot)** <br/> An unoptionated Github bot driven by a configuration file in the repository | [open-bot](http://github.com/open-bot) |
| **[Aws Ses Serverless Example](https://github.com/lakshmantgld/aws-ses-serverless-example)** <br/> AWS SES example in NodeJS using lambda | [lakshmantgld](http://github.com/lakshmantgld) |
| **[Aws Api Gateway Serverless Project Written In Go](https://github.com/yunspace/serverless-golang)** <br/> A serverless project that contains an API Gateway endpoint powered by a Lambda function written in golang and built using [eawsy/aws-lambda-go-shim](https://github.com/eawsy/aws-lambda-go-shim). | [yunspace](http://github.com/yunspace) |
| **[Video Preview And Analysis Service](https://github.com/laardee/video-preview-and-analysis-service)** <br/> An event-driven service that generates labels using Amazon Rekognition and creates preview GIF animation from a video file. | [laardee](http://github.com/laardee) |
| **[Serverless Graphql Api](https://github.com/boazdejong/serverless-graphql-api)** <br/> Serverless GraphQL API using Lambda and DynamoDB | [boazdejong](http://github.com/boazdejong) |
| **[Serverless Screenshot](https://github.com/svdgraaf/serverless-screenshot)** <br/> Serverless Screenshot Service using PhantomJS | [svdgraaf](http://github.com/svdgraaf) |
| **[Serverless Postgraphql](https://github.com/rentrop/serverless-postgraphql)** <br/> GraphQL endpoint for PostgreSQL using postgraphql | [rentrop](http://github.com/rentrop) |
| **[Serverless Messenger Boilerplate](https://github.com/SC5/serverless-messenger-boilerplate)** <br/> Serverless messenger bot boilerplate | [SC5](http://github.com/SC5) |
| **[Serverless Npm Registry](https://github.com/craftship/yith)** <br/> Serverless private npm registry, proxy and cache. | [craftship](http://github.com/craftship) |
| **[Serverless Pokego](https://github.com/jch254/pokego-serverless)** <br/> Serverless-powered API to fetch nearby Pokemon Go data | [jch254](http://github.com/jch254) |
| **[Serverless Weekly2pocket App](https://github.com/s0enke/weekly2pocket)** <br/> Serverless-powered API for sending posts to pocket app | [s0enke](http://github.com/s0enke) |
| **[Serverless Facebook Quotebot](https://github.com/pmuens/quotebot)** <br/> 100% Serverless Facebook messenger chatbot which will respond with inspiring quotes | [pmuens](http://github.com/pmuens) |
| **[Serverless Slack Trevorbot](https://github.com/conveyal/trevorbot)** <br/> Slack bot for info on where in the world is Trevor Gerhardt? | [conveyal](http://github.com/conveyal) |
| **[Serverless Garden Aid](https://github.com/garden-aid/web-bff)** <br/> IoT Garden Aid Backend | [garden-aid](http://github.com/garden-aid) |
| **[Serverless React Boilerplate](https://github.com/99xt/serverless-react-boilerplate)** <br/> A serverless react boilerplate for offline development | [99xt](http://github.com/99xt) |
| **[Serverless Delivery Framework](https://github.com/99xt/serverless-delivery-framework)** <br/> This is a boilerplate for version release pipeline with serverless framework | [99xt](http://github.com/99xt) |
| **[Serverless Mailgun Slack](https://github.com/Marcus-L/serverless-mailgun-slack)** <br/> A Serverless function for posting to a Slack Webhook in response to a Mailgun route | [Marcus-L](http://github.com/Marcus-L) |
| **[Pfs Email Serverless](https://github.com/SCPR/pfs-email-serverless)** <br/> This is a lambda function created by the serverless framework. It searches through members in our mongodb who have not been sent emails and sends them an email with their custom token to unlock the pledge free stream. It then marks those members off as already receiving the email. | [SCPR](http://github.com/SCPR) |
| **[Plaid Cashburndown Service](https://github.com/cplee/cashburndown-service)** <br/> Service for calculating cash burndown with plaid. Frontend code can be found here: https://github.com/cplee/cashburndown-site | [cplee](http://github.com/cplee) |
| **[Cordis Serverless](https://github.com/marzeelabs/cordis-serverless)** <br/> A serverless API for EU Cordis data | [marzeelabs](http://github.com/marzeelabs) |
| **[Serverless Newsletter Signup](https://github.com/ivanderbu2/serverless-newsletter-signup)** <br/> Saves user details into DynamoDB table. Required values are email, first_name and last_name. | [ivanderbu2](http://github.com/ivanderbu2) |
| **[Serverless Slack Cron](https://github.com/ivanderbu2/serverless-slack-cron)** <br/> Lambda function which sends messages to Slack channel in regular intervals via cron trigger. | [ivanderbu2](http://github.com/ivanderbu2) |
| **[Giphy Bot](https://github.com/tywong/lambda-workshop-2016/tree/master/giphy-bot)** <br/> giphy-bot for Facebook chat | [tywong](http://github.com/tywong) |
| **[Jwt Lambda Python](https://github.com/mikaelmork/jwt-auth.serverless)** <br/> Minimal proof-of-concept implementation of JWT with Serverless / AWS Lambda | [mikaelmork](http://github.com/mikaelmork) |
| **[Sls Access Counter](https://github.com/takahashim/sls-access-counter)** <br/> Site visitor counter | [takahashim](http://github.com/takahashim) |
| **[Sls Form Mail](https://github.com/takahashim/sls-form-mail)** <br/> Send SNS email from form data | [takahashim](http://github.com/takahashim) |
| **[Serverless Python Sample](https://github.com/bennybauer/serverless-python-sample)** <br/> A simple serverless python sample with REST API endpoints and dependencies | [bennybauer](http://github.com/bennybauer) |
| **[Serverless Msg Gateway](https://github.com/yonahforst/msg-gateway)** <br/> A messaging aggregator for kik, skype, twilio, telegram, & messenger. Send and receive messages in a standard format. | [yonahforst](http://github.com/yonahforst) |
| **[Serverless Aws Rekognition Finpics](https://github.com/rgfindl/finpics)** <br/> Use AWS Rekognition to provide a faces search of finpics.com | [rgfindl](http://github.com/rgfindl) |
| **[Serverless Slack Emojibot](https://github.com/markhobson/emojibot)** <br/> Serverless slack bot for emoji | [markhobson](http://github.com/markhobson) |
| **[Keboola Developer Portal](https://github.com/keboola/developer-portal)** <br/> Keboola developer portal built with Serverless | [keboola](http://github.com/keboola) |
| **[Serverless Cloudwatch Rds Custom Metrics](https://github.com/AndrewFarley/serverless-cloudwatch-rds-custom-metrics)** <br/> A NodeJS-based MySQL RDS Data Collection script to push Custom Metrics to Cloudwatch with Serverless | [AndrewFarley](http://github.com/AndrewFarley) |
| **[Jrestless Examples](https://github.com/bbilger/jrestless-examples)** <br/> [JRestless](https://github.com/bbilger/jrestless) (Java / JAX-RS) examples for [API Gateway Functions](https://github.com/bbilger/jrestless-examples/tree/master/aws/gateway) ([plain JAX-RS](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-showcase), [Spring](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-spring), [binary data requests/responses](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-binary), [custom authorizers](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-custom-authorizer) and [Cognito User Pool authorizers](https://github.com/bbilger/jrestless-examples/blob/master/aws/gateway/aws-gateway-security-cognito-authorizer)), [SNS Functions](https://github.com/bbilger/jrestless-examples/blob/master/aws/sns/aws-sns-usage-example) (asynchronous communication between functions) and [Service Functions](https://github.com/bbilger/jrestless-examples/blob/master/aws/service/aws-service-usage-example) (synchronous HTTP-like communication between functions - transparent through Feign) | [bbilger](http://github.com/bbilger) |
| **[Sc5 Serverless Boilerplate](https://github.com/SC5/sc5-serverless-boilerplate)** <br/> A boilerplate that contains setup for test-driven development | [SC5](http://github.com/SC5) |
| **[Serverless Blog To Podcast](https://github.com/SC5/serverless-blog-to-podcast)** <br/> Service that reads RSS feed and converts the entries to a podcast feed and audio files using Amazon Polly | [SC5](http://github.com/SC5) |
| **[Offset Trump](https://github.com/FLGMwt/offset-trump)** <br/> Single page app using Serverless (C# runtime) and S3 site hosting. Pledge to do a good thing for the next four years to offset the potential negative effects of the US Presidency | [FLGMwt](http://github.com/FLGMwt) |
| **[Serverless Url Shortener](https://github.com/aletheia/serverless-url-shortener)** <br/> A simple url-shortener, using Serverless framework | [aletheia](http://github.com/aletheia) |
| **[Serverless Html Pdf](https://github.com/calvintychan/serverless-html-pdf)** <br/> Service that convert HTML to PDF using PhantomJS's rasterize example. | [calvintychan](http://github.com/calvintychan) |
| **[Serverless Examples Cached Rds Ws](https://github.com/mugglmenzel/serverless-examples-cached-rds-ws)** <br/> A serverless framework example project that uses API Gateway, ElastiCache, and RDS PostgreSQL. | [mugglmenzel](http://github.com/mugglmenzel) |
| **[Bittman](https://github.com/rhlsthrm/bittman)** <br/> A serverless project that follows a stock trading algorithm and uses scheduled functions to save data to DynamoDB and send emails through Mailgun. | [rhlsthrm](http://github.com/rhlsthrm) |
| **[Adoptable Pet Bot](https://github.com/lynnaloo/adoptable-pet-bot)** <br/> Tweets adoptable pets using Serverless (Node.js) and AWS Lambda | [lynnaloo](http://github.com/lynnaloo) |
| **[Owntracks Serverless](https://github.com/dschep/owntracks-serverless)** <br/> A serverless implementation of the OwnTracks HTTP backend | [dschep](http://github.com/dschep) |
| **[Serverless Modern Koa](https://github.com/barczaG/serverless-modern-koa)** <br/> Serverless modern koa starter kit | [barczaG](http://github.com/barczaG) |
| **[Serverless Reactjs Universal Rendering Boilerplate](https://github.com/TylorShin/react-universal-in-serverless)** <br/> ReactJS web app Starter kit does universal (isomorphic) rendering with Serverless | [TylorShin](http://github.com/TylorShin) |
| **[Open Bot](https://github.com/open-bot/open-bot)** <br/> An unoptionated Github bot driven by a configuration file in the repository | [open-bot](http://github.com/open-bot) |
| **[Aws Ses Serverless Example](https://github.com/lakshmantgld/aws-ses-serverless-example)** <br/> AWS SES example in NodeJS using lambda | [lakshmantgld](http://github.com/lakshmantgld) |
| **[Aws Api Gateway Serverless Project Written In Go](https://github.com/yunspace/serverless-golang)** <br/> A serverless project that contains an API Gateway endpoint powered by a Lambda function written in golang and built using [eawsy/aws-lambda-go-shim](https://github.com/eawsy/aws-lambda-go-shim). | [yunspace](http://github.com/yunspace) |
| **[Video Preview And Analysis Service](https://github.com/laardee/video-preview-and-analysis-service)** <br/> An event-driven service that generates labels using Amazon Rekognition and creates preview GIF animation from a video file. | [laardee](http://github.com/laardee) |
| **[Serverless Es6/7 Crud Api](https://github.com/AnomalyInnovations/serverless-stack-demo-api)** <br/> [Serverless Stack](http://serverless-stack.com) examples of backend CRUD APIs (DynamoDB + Lambda + API Gateway + Cognito User Pool authorizer) for [React.js single-page app](http://demo.serverless-stack.com) | [AnomalyInnovations](http://github.com/AnomalyInnovations) |
<!-- AUTO-GENERATED-CONTENT:END This table is generated from https://github.com/serverless/examples/blob/master/community-examples.json please make additions there -->

View File

@ -2,50 +2,45 @@
This checklist should be worked through when releasing a new Serverless version.
More info about our release process can be found in the [`RELEASE_PROCESS.md`](./RELEASE_PROCESS.md) document.
## Pre-Release
- [ ] Look through all open issues and PRs (if any) of that milestone and close them / move them to another
milestone if still open
- [ ] Look through all closed issues and PRs of that milestone to see what has changed. Run `./scripts/pr-since-last tag` or if you want to run against a specific tag `./scripts/pr-since-last tag v1.0.3` to get a list of all merged PR's since a specific tag
- [ ] Close milestone on Github
- [ ] Create a new release in GitHub for Release Notes (including breaking changes)
- [ ] Look through all closed issues and PRs of that milestone to see what has changed. Run `./scripts/prs-since-last tag` or if you want to run against a specific tag `./scripts/prs-since-last tag v1.20.0` to get a list of all merged PR's since a specific tag
- [ ] Close milestone on GitHub
- [ ] Create a new draft release in GitHub
# Testing
- [ ] Create a Serverless service (with some events), deploy and test it intensively
- [ ] Run integration test repository against the current release
- [ ] Look through the milestone and test all of the new major changes
- [ ] Run "npm test"
- [ ] Run "npm run simple-integration-test"
- [ ] Run "npm run complex-integration-test"
- [ ] Run `npm test`
- [ ] Run `npm run simple-integration-test`
- [ ] Run `npm run complex-integration-test`
## Prepare Package
- [ ] Create a new branch to bump version in package.json
- [ ] Install the latest NPM version or Docker container with latest Node and NPM
- [ ] Bump version in package.json, remove `node_modules` folder and run `npm install` and `npm prune --production && npm shrinkwrap`
- [ ] Update CHANGELOG.md (including breaking changes)
- [ ] Create a new branch to bump version in `package.json`
- [ ] Install the latest `npm` version or Docker container with latest `node` and `npm`
- [ ] Bump version in `package.json`, remove `node_modules` folder and run `npm install` and `npm prune --production && npm shrinkwrap`
- [ ] Look through closed PRs and update `CHANGELOG.md`
- [ ] Make sure all files that need to be pushed are included in `package.json -> files`
- [ ] Send PR and merge PR with new version to be released
- [ ] Go back to branch you want to release from (e.g. master or v1) and pull bumped version changes from Github
- [ ] Add the changes you made to `CHANGELOG.md` to the description of the GitHub release draft
- [ ] Go back to branch you want to release from (e.g. `master`) and pull bumped version changes from GitHub
- [ ] Make sure there are no local changes to your repository (or reset with `git reset --hard HEAD`)
- [ ] Check package.json and npm-shrinkwrap.json version config to make sure it fits what we want to release. *DO THIS, DON'T SKIP, DON'T BE LAZY!!!*
- [ ] Check `package.json`, `package-lock.json` and `npm-shrinkwrap.json` version config to make sure it fits what we want to release
## Git Tagging
- [ ] Create a git tag with the version (`git tag <VersionName>`: `git tag v1.0.0`)
- [ ] Push the git tag (`git push origin <VersionName>`)
## Releasing
## Segment Configuration
- [ ] Update Segment.io key in [segment.js file](https://github.com/serverless/serverless/blob/d31057239d232181128d978c392bdecbcb9fcf1b/lib/utils/segment.js#L7) (never push the key to GitHub and revert afterwards with `git checkout .`)
- [ ] Check twice if you've used the correct key (**if in doubt ask which one to pick!**)
- [ ] Run `./bin/serverless help` and filter for this new version in the Segment debugger to make sure data is sent to Segment for this new version
## Release to NPM
- [ ] Log into npm (`npm login`)
- [ ] Publish to NPM (`npm publish —-tag <TagForInstall>`, e.g. `npm publish --tag beta` or `npm publish` to release latest production framework)
- [ ] Update Alpha/Beta accordingly so they point to the latest release. If its an Alpha Release the Beta tag should point to the latest stable release. This way Alpha/Beta always either point to something stable or the highest priority release in Alpha/Beta stage (`npm dist-tag add serverless@<VERSION> alpha`, `npm dist-tag add serverless@<VERSION> beta`)
- [ ] Publish the GitHub release draft (Travis CI will automatically publish the new release to `npm`)
## Validate Release
- [ ] Validate NPM install works (`npm install -g serverless@<TagForInstall>` or `npm install -g serverless` if latest is released)
- [ ] Check Segment.com production data if events are coming in correctly with the new version
- [ ] Make sure you run `git checkout .` to revert adding Segment write key
- [ ] Validate that `npm install` works (`npm install -g serverless@<new-tag>` or `npm install -g serverless` if latest is released)
## Post-Release
- [ ] Run `./scripts/generate-release-contributors-list <old-tag> <new-tag>` and hand the generated list over to the release blog post author

51
RELEASE_PROCESS.md Normal file
View File

@ -0,0 +1,51 @@
# Release Process
This document contains all the necessary information about out release process.
### Merge freeze
A "merge freeze" will be applied a few days before the release. This means that **NOTHING** will be added to the release branch.
A "merge freeze" ends once the release was published.
## Different types of releases
**Note:** More about versioning can be found in our dedicated [VERSIONING file](https://github.com/serverless/serverless/blob/master/VERSIONING.md).
Releases can come in different flavors. Here's a list with the most common release types and how they're treated
### Minor / Major release
The minor / major release is a planned release which includes all the changes added since the last minor / major release (including bugfixes). The user should pick up the latest minor / major release automatically when installing / updating Serverless.
The minor / major releases is released at a pre-defined time.
#### Versioning / tagging
Assuming our current version is `v1.1.0`.
The minor release would be `v1.2.0`. The major release would be `v2.0.0`.
### Patch release
Patch releases should **only** include critical bug fixes and released ASAP. The user should pick up the latest patch release automatically when installing / updating Serverless.
#### Versioning / tagging
Assuming our current version is `v1.1.0`.
The patch release would be `v1.1.1`.
### Alpha release
Alpha releases are created to have a sneak peek into the upcoming feature set of the new release. They're also used for pre-release QA / internal usage.
Alpha releases are not scheduled and can be pushed multiple times throughout a development phase.
Alpha releases should never be installed automatically when the user installs / updates Serverless. The user should be forced to explicitly name the alpha release during the installation / update phase (e.g. via `npm install --global serverless@alpha`).
#### Versioning / tagging
Assuming our current version is `v1.1.0`.
The alpha releas would be `v1.2.0-alpha.1`. A subsequent alpha release would be `v1.2.0-alpha.2` etc.

1
assets/.gitkeep Normal file
View File

@ -0,0 +1 @@

BIN
assets/framework_repo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -51,6 +51,14 @@ services:
image: microsoft/dotnet:1.0.4-sdk
volumes:
- ./tmp/serverless-integration-test-aws-fsharp:/app
aws-nodejs-typescript:
image: node:6.10.3
volumes:
- ./tmp/serverless-integration-test-aws-nodejs-typescript:/app
aws-nodejs-ecma-script:
image: node:6.10.3
volumes:
- ./tmp/serverless-integration-test-aws-nodejs-ecma-script:/app
google-nodejs:
image: node:6.9.1
volumes:

67
docs/platform/README.md Normal file
View File

@ -0,0 +1,67 @@
<!--
title: Serverless - Platform Documentation
menuText: Platform
layout: Doc
menuItems:
- {menuText: emit, path: /framework/docs/platform/commands/emit/}
- {menuText: login, path: /framework/docs/platform/commands/login/}
- {menuText: logout, path: /framework/docs/platform/commands/logout/}
- {menuText: run, path: /framework/docs/platform/commands/run/}
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform)
<!-- DOCS-SITE-LINK:END -->
# Serverless Platform (Beta)
The Serverless Platform is currently in experimental beta. If you'd like to participate in the beta, simply follow the instructions below.
## Set-Up
Make sure you have Node.js installed and run:
```sh
$ npm i serverless -g
```
Then, check the version to make sure you are using V1.20.0, or later:
```sh
$ serverless -v
```
## Usage
First, register or log in to the Serverless platform in via the CLI
```sh
$ serverless login
```
After logging into the platform via the Serverless framework CLI every deploy will be published **privately** to the Serverless Platform. It allows you to view and share your deployed services.
Give it a try with a new service, or an existing service:
```sh
$ serverless deploy
```
Then visit https://platform.serverless.com/ in your browser.
## Beta CLI Commands
Logging in to the platform enables access to beta features of the Serverless framework.
### [`serverless run`](./commands/run.md)
Start local development mode for a Serverless service. This mode downloads and installs the [event-gateway](https://github.com/serverless/event-gateway) and the [serverless emulator](https://github.com/serverless/emulator). Both of these are used to emulate a serverless service and develop against them locally.
### [`serverless emit`](./commands/emit.md)
Emit an event to an event-gateway.
### [`serverless login`](./commands/login.md)
Register or log in to the platform.
### [`serverless logout`](./commands/logout.md)
Logout of the platform.

View File

@ -0,0 +1,26 @@
<!--
title: Serverless - Platform Documentation
menuText: commands
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform)
<!-- DOCS-SITE-LINK:END -->
## Beta CLI Commands
Logging in to the platform enables access to beta features of the Serverless framework.
### [`serverless run`](./run.md)
Start local development mode for a Serverless service. This mode downloads and installs the [event-gateway](https://github.com/serverless/event-gateway) and the [serverless emulator](https://github.com/serverless/emulator). Both of these are used to emulate a serverless service and develop against them locally.
### [`serverless emit`](./emit.md)
Emit an event to an event-gateway.
### [`serverless login`](./login.md)
Register or log in to the platform.
### [`serverless logout`](./logout.md)
Logout of the platform.

View File

@ -0,0 +1,49 @@
<!--
title: Serverless Framework Commands - Emit
menuText: emit
menuOrder: 11
description: Emit an event to a serverless service
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform/commands/emit)
<!-- DOCS-SITE-LINK:END -->
# Emit
The `emit` command emits an event to a serverless service
```bash
serverless emit -n my.event -d '{"foo":"bar"}'
# Shorthand
sls emit -n my.event -d '{"foo":"bar"}'
```
## Options
- `--name` or `-n` The event name. **Required**.
- `--data` or `-d` The event data
- `--path` or `-p` Path to JSON or YAML file holding event data',
- `--url` or `-u` Event Gateway address
- `--datatype` or `-t` Data type for the event data. By default set to application/json
## Provided lifecycle Events
- `emit:emit`
## Examples
### Emitting an Event to locally running Event Gateway
```bash
serverless emit -n my.event -d '{"foo":"bar"}'
```
### Emitting an Event to a remote Event Gateway
```bash
serverless emit -n foo.bar -d '{"foo":"bar"}' -u https://mygateway.com
```

View File

@ -0,0 +1,26 @@
<!--
title: Serverless Framework Commands - Login
menuText: login
menuOrder: 11
description: Login to the serverless platform
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform/commands/login)
<!-- DOCS-SITE-LINK:END -->
# Login
The `login` command logs users into the serverless platform.
It will create a new serverless platform account if one doesn't already exist.
*This command opens a browser window*
```bash
serverless login
# Shorthand
sls login
```

View File

@ -0,0 +1,22 @@
<!--
title: Serverless Framework Commands - Logout
menuText: logout
menuOrder: 11
description: Logout to the serverless platform
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform/commands/logout)
<!-- DOCS-SITE-LINK:END -->
# Logout
The `logout` command logs users out the serverless platform.
```bash
serverless logout
# Shorthand
sls logout
```

View File

@ -0,0 +1,39 @@
<!--
title: Serverless Framework Commands - Run
menuText: run
menuOrder: 11
description: Run the serverless service locally
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/platform/commands/run)
<!-- DOCS-SITE-LINK:END -->
# Run
The `run` command starts the serverless service locally.
```bash
serverless run
# Shorthand
sls run
```
## Supported Languages
NOTE: *currently supports node js 6.3+ only*
## Supported Providers
- AWS Lambda
- Google Cloud Functions (Pub/Sub only, HTTP coming soon)
## Options
- `--debug` or `-d` Start the emulator in debug mode
- `--eport` or `-e` The Event Gateway API port. Defaults to 4000
- `--cport` or `-c` The Event Gateway configuration port. Defaults to 4001
- `--lport` or `-l` The Emulator port. Defaults to 4002
## Provided lifecycle events
- `run:run`

View File

@ -12,7 +12,7 @@ layout: Doc
Welcome to the Serverless AWS Functions documentation!
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)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** [AWS system credentials](./guide/credentials.md) are required for using serverless + AWS.

View File

@ -14,4 +14,4 @@ Welcome to the Serverless AWS Lambda CLI Reference! Please select a section on
**Note:** Before continuing [AWS 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](https://gitter.im/serverless/serverless)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)

View File

@ -22,6 +22,7 @@ serverless config credentials --provider provider --key key --secret secret
- `--key` or `-k` The `aws_access_key_id`. **Required**.
- `--secret` or `-s` The `aws_secret_access_key`. **Required**.
- `--profile` or `-n` The name of the profile which should be created.
- `--overwrite` or `-o` Overwrite the profile if it exists.
## Provided lifecycle events
@ -44,3 +45,13 @@ serverless config credentials --provider aws --key 1234 --secret 5678 --profile
```
This example create and configure a `custom-profile` profile with the `aws_access_key_id` of `1234` and the `aws_secret_access_key` of `5678`.
### Update an existing profile
```bash
serverless config credentials --provider aws --key 1234 --secret 5678 --profile custom-profile --overwrite
```
This example overwrite `custom-profile` profile with the `aws_access_key_id` of `1234` and the `aws_secret_access_key` of `5678`.
If the profile do not exist, it will be added anyway.

View File

@ -41,6 +41,8 @@ To see a list of available templates run `serverless create --help`
Most commonly used templates:
- aws-nodejs
- aws-nodejs-typescript
- aws-nodejs-ecma-script
- aws-python
- aws-python3
- aws-groovy-gradle

View File

@ -23,6 +23,9 @@ serverless invoke local --function functionName
- `--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 as the `event`. This path is relative to the root directory of the service.
- `--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.
- `--raw` Pass data as a raw string even if it is JSON. If not set, JSON data are parsed and passed as an object.
- `--contextPath` or `-x`, The path to a json file holding input context to be passed to the invoked function. This path is relative to the root directory of the service.
- `--context` or `-c`, String data to be passed as a context to your function. Same like with `--data`, context included in `--contextPath` will overwrite the context you passed with `--context` flag.
## Environment
@ -51,6 +54,13 @@ serverless invoke local --function functionName --data "hello world"
serverless invoke local --function functionName --data '{"a":"bar"}'
```
### Local function invocation with custom context
```bash
serverless invoke local --function functionName --context "hello world"
```
### Local function invocation with data from standard input
```bash
@ -76,6 +86,12 @@ This example will pass the json data in the `lib/data.json` file (relative to th
}
```
### Local function invocation with context passing
```bash
serverless invoke local --function functionName --contextPath lib/context.json
```
This example will pass the json context in the `lib/context.json` file (relative to the root of the service) while invoking the specified/deployed function.
### Limitations
Currently, `invoke local` only supports the NodeJs and Python runtimes.

View File

@ -23,6 +23,7 @@ serverless invoke [local] --function functionName
- `--stage` or `-s` The stage in your service you want to invoke your function in.
- `--region` or `-r` The region in your stage that you want to invoke your function in.
- `--data` or `-d` String data to be passed as an event to your function. By default data is read from standard input.
- `--raw` Pass data as a raw string even if it is JSON. If not set, JSON data are parsed and passed as an object.
- `--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`.
@ -44,6 +45,7 @@ serverless invoke local --function functionName
- `--path` or `-p` The path to a json file holding input data to be passed to the invoked function as the `event`. This path is relative to the
root directory of the service.
- `--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.
- `--raw` Pass data as a raw string even if it is JSON. If not set, JSON data are parsed and passed as an object.
## Examples

View File

@ -14,6 +14,6 @@ Welcome to the Serverless AWS Lambda 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](https://gitter.im/serverless/serverless)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** Before continuing [AWS system credentials](../guide/credentials.md) are required for using the CLI.

View File

@ -28,4 +28,4 @@ Have an example? Submit a PR or [open an issue](https://github.com/serverless/ex
| [Serverless Data Pipeline](https://github.com/serverless/examples/tree/master/aws-node-text-analysis-via-sns-post-processing) <br/> Example demonstrates how to setup a simple data processing pipeline | nodeJS |
| [Aws Python Simple Http Endpoint](https://github.com/serverless/examples/tree/master/aws-python-simple-http-endpoint) <br/> Example demonstrates how to setup a simple HTTP GET endpoint with python | python |
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)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)

View File

@ -14,6 +14,6 @@ Welcome to the Serverless AWS Lambda 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](https://gitter.im/serverless/serverless)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** Before continuing [AWS system credentials](./credentials.md) are required for using the CLI.

View File

@ -63,6 +63,8 @@ export AWS_ACCESS_KEY_ID=<your-key-here>
export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>
# AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are now available for serverless to use
serverless deploy
# 'export' command is valid only for unix shells. In Windows - use 'set' instead of 'export'
```
#### Using AWS Profiles
@ -130,7 +132,7 @@ The AWS region setting is to prevent issues with specific services, so adapt if
##### Using the `aws-profile` option
You can always speficy the profile which should be used via the `aws-profile` option like this:
You can always specify the profile which should be used via the `aws-profile` option like this:
```bash
serverless deploy --aws-profile devProfile

View File

@ -303,16 +303,18 @@ provider:
These versions are not cleaned up by serverless, so make sure you use a plugin or other tool to prune sufficiently old versions. The framework can't clean up versions because it doesn't have information about whether older versions are invoked or not. This feature adds to the number of total stack outputs and resources because a function version is a separate resource from the function it refers to.
## DeadLetterConfig
## Dead Letter Queue (DLQ)
You can setup `DeadLetterConfig` with the help of a SNS topic and the `onError` config parameter.
When AWS lambda functions fail, they are [retried](http://docs.aws.amazon.com/lambda/latest/dg/retries-on-errors.html). If the retries also fail, AWS has a feature to send information about the failed request to a SNS topic or SNS queue, called the [Dead Letter Queue](http://docs.aws.amazon.com/lambda/latest/dg/dlq.html), which you can use to track and diagnose and react to lambda failures.
The SNS topic needs to be created beforehand and provided as an `arn` on the function level.
You can setup a dead letter queue for your serverless functions with the help of a SNS topic and the `onError` config parameter.
**Note:** You can only provide one `onError` config per function.
### DLQ with SNS
The SNS topic needs to be created beforehand and provided as an `arn` on the function level.
```yml
service: service
@ -328,7 +330,7 @@ functions:
### DLQ with SQS
The `onError` config currently only supports SNS topic arns due to a race condition when using SQS queue arns and updating the IAM role.
Although Dead Letter Queues support both SNS topics and SQS queues, the `onError` config currently only supports SNS topic arns due to a race condition when using SQS queue arns and updating the IAM role.
We're working on a fix so that SQS queue arns will be supported in the future.

View File

@ -169,7 +169,14 @@ resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:${region}:${accountId}:log-group:/aws/lambda/*:*:*
Resource:
- 'Fn::Join':
- ':'
-
- 'arn:aws:logs'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
- Effect: Allow
Action:
- ec2:CreateNetworkInterface
@ -200,7 +207,14 @@ resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:${region}:${accountId}:log-group:/aws/lambda/*:*:*
Resource:
- 'Fn::Join':
- ':'
-
- 'arn:aws:logs'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
- Effect: "Allow"
Action:
- "s3:PutObject"
@ -252,7 +266,14 @@ resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:${region}:${accountId}:log-group:/aws/lambda/*:*:*
Resource:
- 'Fn::Join':
- ':'
-
- 'arn:aws:logs'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
- Effect: "Allow"
Action:
- "s3:PutObject"
@ -284,7 +305,14 @@ resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:${region}:${accountId}:log-group:/aws/lambda/*:*:*
Resource:
- 'Fn::Join':
- ':'
-
- 'arn:aws:logs'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
- Effect: Allow
Action:
- ec2:CreateNetworkInterface

View File

@ -20,7 +20,7 @@ Go to the official [Node.js website](https://nodejs.org), download and follow th
**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.
You can verify that Node.js is installed successfully by running `node --version` in your terminal. You should see the corresponding Node version number printed out.
### Installing the Serverless Framework

View File

@ -47,7 +47,7 @@ $ cd my-service
3. **Invoke the Function**
Invokes an Function and returns logs.
Invokes a Function and returns logs.
```bash
serverless invoke -f hello -l

View File

@ -200,5 +200,6 @@ resources:
Description: The ARN for the User's Table
Value:
"Fn::GetAtt": [ usersTable, Arn ]
Export: ${self:service}:${opt:stage}:UsersTableArn # see Fn::ImportValue to use in other services and http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html for documentation on use.
Export:
Name: ${self:service}:${opt:stage}:UsersTableArn # see Fn::ImportValue to use in other services and http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html for documentation on use.
```

View File

@ -37,7 +37,7 @@ comments/
```
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.
**Note:** Currently, every service will create a separate REST API on AWS API Gateway. Due to a limitation with AWS API Gateway, you can only have a custom domain per one REST API. If you plan on making a large REST API, please make note of this limitation. Also, [a fix is in the works][https://github.com/serverless/serverless/issues/3078] and is a top priority.
**Note:** Currently, every service will create a separate REST API on AWS API Gateway. Due to a limitation with AWS API Gateway, you can only have a custom domain per one REST API. If you plan on making a large REST API, please make note of this limitation. Also, [a fix is in the works](https://github.com/serverless/serverless/issues/3078) and is a top priority.
## Creation
@ -51,6 +51,8 @@ serverless create --template aws-nodejs --path myService
Here are the available runtimes for AWS Lambda:
* aws-nodejs
* aws-nodejs-typescript
* aws-nodejs-ecma-script
* aws-python
* aws-python3
* aws-groovy-gradle
@ -160,7 +162,13 @@ Create this file and add event data so you can invoke your function with the dat
When you deploy a Service, all of the Functions, Events and Resources in your `serverless.yml` are translated to an AWS CloudFormation template and deployed as a single CloudFormation stack.
To deploy a service, use the `deploy` command:
To deploy a service, first `cd` into the relevant service directory:
```bash
cd my-service
```
Then use the `deploy` command:
```bash
serverless deploy

View File

@ -123,8 +123,9 @@ functions:
handler: handler.hello
```
In the above example, the value for `myKey` in the `myBucket` S3 bucket will be looked up and used to populate the variable.
## 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:
## Reference Variables in other Files
You can reference variables in other YAML or JSON files. To reference variables in other YAML files use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. To reference variables in other JSON files use the `${file(./myFile.json):someProperty}` syntax. It is important that the file you are referencing has the correct suffix, or file extension, for its file type (`.yml` for YAML or `.json` for JSON) in order for it to be interpreted correctly. Here's an example:
```yml
# myCustomFile.yml
@ -147,7 +148,43 @@ functions:
- 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.
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. Additionally you can request properties that contain arrays from either YAML or JSON reference files. Here's a YAML example for an events array:
```yml
myevents:
- schedule:
rate: rate(1 minute)
```
and for JSON:
```json
{
"myevents": [{
"schedule" : {
"rate" : "rate(1 minute)"
}
}]
}
```
In your `serverless.yml`, depending on the type of your source file, either have the following syntax for YAML:
```yml
functions:
hello:
handler: handler.hello
events: ${file(./myCustomFile.yml):myevents
```
or for a JSON reference file use this sytax:
```yml
functions:
hello:
handler: handler.hello
events: ${file(./myCustomFile.json):myevents
```
## Reference Variables in Javascript Files
@ -273,6 +310,7 @@ provider:
stage: dev
custom:
myStage: ${opt:stage, self:provider.stage}
myRegion: ${opt:region, 'us-west-1'}
functions:
hello:
@ -292,7 +330,7 @@ service: new-service
provider:
name: aws
runtime: nodejs6.10
variableSyntax: "\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}" # notice the double quotes for yaml to ignore the escape characters!
variableSyntax: "\\${([ ~:a-zA-Z0-9._\'\",\\-\\/\\(\\)]+?)}" # notice the double quotes for yaml to ignore the escape characters!
custom:
myStage: ${{opt:stage}}

View File

@ -12,7 +12,7 @@ layout: Doc
Welcome to the Serverless Azure Functions documentation!
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)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** [Azure Functions system credentials](./guide/credentials.md) are required for using serverless + Azure Functions.

View File

@ -16,4 +16,4 @@ Have an example? Submit a PR or [open an issue](https://github.com/serverless/ex
|:--------------------------- |:-----|
| [azure Node Simple](https://github.com/serverless/examples/tree/master/azure-node-simple-http-endpoint) <br/> Boilerplate project repository for Azure 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/)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)

View File

@ -115,7 +115,13 @@ When you deploy a Service, all of the Functions, and Events 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:
To deploy a service, first `cd` into the relevant service directory:
```bash
cd my-service
```
Then use the `deploy` command:
```bash
serverless deploy

View File

@ -41,19 +41,78 @@ custom:
functions:
hello:
handler: handler.hello
events:
- timer: ${self:custom.globalSchedule}
handler: handler.hello
events:
- timer: ${self:custom.globalSchedule}
world:
handler: handler.world
events:
- timer: ${self:custom.globalSchedule}
handler: handler.world
events:
- timer: ${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.
## Reference Variables in other Files
You can reference variables in other YAML or JSON files. To reference variables in other YAML files use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. To reference variables in other JSON files use the `${file(./myFile.json):someProperty}` syntax. It is important that the file you are referencing has the correct suffix, or file extension, for its file type (`.yml` for YAML or `.json` for JSON) in order for it to be interpreted correctly. Here's an example:
```yml
# myCustomFile.yml
cron: cron(0 * * * *)
```
```yml
# serverless.yml
service: new-service
provider: azure
custom: ${file(./myCustomFile.yml)} # You can reference the entire file
functions:
hello:
handler: handler.hello
events:
- timer: ${file(./myCustomFile.yml):cron} # Or you can reference a specific property
world:
handler: handler.world
events:
- timer: ${self:custom.cron} # 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 `cron` property. It's completely recursive and you can go as deep as you want. Additionally you can request properties that contain arrays from either YAML or JSON reference files. Here's a YAML example for an events array:
```yml
myevents:
- timer: cron(0 * * * *)
```
and for JSON:
```json
{
"myevents": [{
"timer" : "cron(0 * * * *)"
}]
}
```
In your serverless.yml, depending on the type of your source file, either have the following syntax for YAML
```yml
functions:
hello:
handler: handler.hello
events: ${file(./myCustomFile.yml):myevents
```
or for a JSON reference file use this sytax:
```yml
functions:
hello:
handler: handler.hello
events: ${file(./myCustomFile.json):myevents
```
## Reference Variables in JavaScript Files
You can reference JavaScript files to add dynamic data into your variables.

View File

@ -12,7 +12,7 @@ layout: Doc
Welcome to the Serverless Google Cloud Functions documentation!
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)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** [Google Cloud system credentials](./guide/credentials.md) are required for using the CLI.

View File

@ -16,4 +16,4 @@ Have an example? Submit a PR or [open an issue](https://github.com/serverless/ex
|:--------------------------- |:-----|
| [Google Node Simple](https://github.com/serverless/examples/tree/master/google-node-simple-http-endpoint) <br/> Boilerplate project repository for Google Cloud 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/)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)

View File

@ -18,7 +18,7 @@ Serverless is a [Node.js](https://nodejs.org) CLI tool so the first thing you ne
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.
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.
You can verify that Node.js is installed successfully by running `node --version` in your terminal. You should see the corresponding Node version number printed out.
### Installing the Serverless Framework

View File

@ -100,7 +100,13 @@ The `index.js` file contains your exported functions.
When you deploy a Service, all of the Functions, and Events in your `serverless.yml` are translated into calls to the Google Cloud API to dynamically define those resources.
To deploy a service, use the `deploy` command:
To deploy a service, first `cd` into the relevant service directory:
```bash
cd my-service
```
Then use the `deploy` command:
```bash
serverless deploy

View File

@ -50,6 +50,72 @@ functions:
In the above example you're setting a global event resource for all functions by referencing the `resource` property in the same `serverless.yml` file. This way, you can easily change the event resource for all functions whenever you like.
## Reference Variables in other Files
You can reference variables in other YAML or JSON files. To reference variables in other YAML files use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. To reference variables in other JSON files use the `${file(./myFile.json):someProperty}` syntax. It is important that the file you are referencing has the correct suffix, or file extension, for its file type (`.yml` for YAML or `.json` for JSON) in order for it to be interpreted correctly. Here's an example:
```yml
# myCustomFile.yml
topic: projects/*/topics/my-topic
```
```yml
# serverless.yml
service: new-service
provider: google
custom: ${file(./myCustomFile.yml)} # You can reference the entire file
functions:
hello:
handler: pubSub.hello
events:
- event:
eventType: providers/cloud.pubsub/eventTypes/topics.publish
resource: ${file(./myCustomFile.yml):topic} # Or you can reference a specific property
world:
handler: pubSub.hello
events:
eventType: providers/cloud.pubsub/eventTypes/topics.publish
resource: ${self:custom.topic} # 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 `topic` property. It's completely recursive and you can go as deep as you want. Additionally you can request properties that contain arrays from either YAML or JSON reference files. Here's a YAML example for an events array:
```yml
myevents:
- event:
eventType: providers/cloud.pubsub/eventTypes/topic.publish
resource: projects/*/topics/my-topic
```
and for JSON:
```json
{
"myevents": [{
"event" : {
"eventType": "providers/cloud.pubsub/eventTypes/topic.publish",
"resource" : "projects/*/topics/my-topic"
}
}]
}
```
In your serverless.yml, depending on the type of your source file, either have the following syntax for YAML
```yml
functions:
hello:
handler: pubSub.hello
events: ${file(./myCustomFile.yml):myevents
```
or for a JSON reference file use this sytax:
```yml
functions:
hello:
handler: pubSub.hello
events: ${file(./myCustomFile.json):myevents
```
## Reference Variables in JavaScript Files
You can reference JavaScript files to add dynamic data into your variables.

View File

@ -12,7 +12,7 @@ layout: Doc
Welcome to the Serverless Apache OpenWhisk documentation!
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)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)
**Note:** [Apache OpenWhisk system credentials](./guide/credentials.md) are required for using serverless + openwhisk.

View File

@ -18,4 +18,4 @@ Have an example? Submit a PR or [open an issue](https://github.com/serverless/ex
| [OpenWhisk Python Simple](https://github.com/serverless/examples/tree/master/openwhisk-python-simple) <br/> Boilerplate project repository for OpenWhisk provider with Serverless Framework. | python |
| [OpenWhisk Swift Simple](https://github.com/serverless/examples/tree/master/openwhisk-swift-simple) <br/> Boilerplate project repository for OpenWhisk provider with Serverless Framework. | swift |
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](http://forum.serverless.com/)
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://forum.serverless.com/)

View File

@ -20,7 +20,7 @@ Go to the official [Node.js website](https://nodejs.org), download and follow th
**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.
You can verify that Node.js is installed successfully by running `node --version` in your terminal. You should see the corresponding Node version number printed out.
### Installing the Serverless Framework

View File

@ -107,7 +107,13 @@ Create this file and add event data so you can invoke your function with the dat
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:
To deploy a service, first `cd` into the relevant service directory:
```bash
cd my-service
```
Then use the `deploy` command:
```bash
serverless deploy

View File

@ -79,8 +79,8 @@ functions:
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:
## 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. Here's an example:
```yml
# myCustomFile.yml
@ -103,7 +103,37 @@ functions:
- 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.
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. Additionally you can request properties that contain arrays from either YAML or JSON reference files. Here's a YAML example for an events array:
```yml
myevents:
- schedule: cron(0 * * * *)
```
and for JSON:
```json
{
"myevents": [{
"schedule" : "cron(0 * * * *)"
}]
}
```
In your serverless.yml, depending on the type of your source file, either have the following syntax for YAML
```yml
functions:
hello:
handler: handler.hello
events: ${file(./myCustomFile.yml):myevents
```
or for a JSON reference file use this sytax:
```yml
functions:
hello:
handler: handler.hello
events: ${file(./myCustomFile.json):myevents
```
## Reference Variables in Javascript Files

View File

@ -120,24 +120,54 @@ class CLI {
}
generateMainHelp() {
let platformCommands;
let frameworkCommands;
if (this.loadedCommands) {
const commandKeys = Object.keys(this.loadedCommands);
const sortedCommandKeys = _.sortBy(commandKeys);
const partitionedCommandKeys = _.partition(sortedCommandKeys,
(key) => this.loadedCommands[key].platform);
platformCommands = _.fromPairs(
_.map(partitionedCommandKeys[0], key => [key, this.loadedCommands[key]])
);
frameworkCommands = _.fromPairs(
_.map(partitionedCommandKeys[1], key => [key, this.loadedCommands[key]])
);
}
this.consoleLog('');
this.consoleLog(chalk.yellow.underline('Commands'));
this.consoleLog(chalk.dim('* Serverless documentation: http://docs.serverless.com'));
this.consoleLog(chalk.dim('* You can run commands with "serverless" or the shortcut "sls"'));
this.consoleLog(chalk.dim('* Pass "--verbose" to this command to get in-depth plugin info'));
this.consoleLog(chalk.dim('* Pass "--help" after any <command> for contextual help'));
this.consoleLog('');
if (this.loadedCommands) {
const commandKeys = Object.keys(this.loadedCommands);
const sortedCommandKeys = _.sortBy(commandKeys);
const sortedCommands = _.fromPairs(
_.map(sortedCommandKeys, key => [key, this.loadedCommands[key]])
);
this.consoleLog(chalk.yellow.underline('Framework'));
this.consoleLog(chalk.dim('* Documentation: https://serverless.com/framework/docs/'));
_.forEach(sortedCommands, (details, command) => {
this.consoleLog('');
if (!_.isEmpty(frameworkCommands)) {
_.forEach(frameworkCommands, (details, command) => {
this.displayCommandUsage(details, command);
});
} else {
this.consoleLog('No commands found');
}
this.consoleLog('');
this.consoleLog(chalk.yellow.underline('Platform (Beta)'));
// eslint-disable-next-line max-len
this.consoleLog(chalk.dim('* The Serverless Platform is currently in experimental beta. Follow the docs below to get started.'));
this.consoleLog(chalk.dim('* Documentation: https://serverless.com/platform/docs/'));
this.consoleLog('');
if (!_.isEmpty(platformCommands)) {
_.forEach(platformCommands, (details, command) => {
this.displayCommandUsage(details, command);
});
} else {

View File

@ -71,6 +71,11 @@ class PluginManager {
this.addPlugin(Plugin);
} catch (error) {
// Rethrow the original error in case we're in debug mode.
if (process.env.SLS_DEBUG) {
throw error;
}
const errorMessage = [
`Serverless plugin "${plugin}" not found.`,
' Make sure it\'s installed and listed in the "plugins" section',

View File

@ -6,6 +6,7 @@ const Serverless = require('../../lib/Serverless');
const CLI = require('../../lib/classes/CLI');
const Create = require('../../lib/plugins/create/create');
const _ = require('lodash');
const path = require('path');
const fs = require('fs');
const fse = require('fs-extra');
@ -26,6 +27,12 @@ describe('PluginManager', () => {
class ServicePluginMock2 {}
class BrokenPluginMock {
constructor() {
throw new Error('Broken plugin');
}
}
class Provider1PluginMock {
constructor() {
this.provider = 'provider1';
@ -528,6 +535,7 @@ describe('PluginManager', () => {
describe('#loadPlugins()', () => {
beforeEach(() => {
mockRequire('ServicePluginMock1', ServicePluginMock1);
mockRequire('BrokenPluginMock', BrokenPluginMock);
});
it('should throw an error when trying to load unknown plugin', () => {
@ -549,6 +557,26 @@ describe('PluginManager', () => {
expect(consoleLogStub.calledOnce).to.equal(true);
});
it('should throw an error when trying to load a broken plugin (without SLS_DEBUG)', () => {
const servicePlugins = ['BrokenPluginMock'];
expect(() => pluginManager.loadPlugins(servicePlugins))
.to.throw(serverless.classes.Error);
});
it('should forward any errors when trying to load a broken plugin (with SLS_DEBUG)', () => {
const servicePlugins = ['BrokenPluginMock'];
return BbPromise.try(() => {
_.set(process.env, 'SLS_DEBUG', '*');
expect(() => pluginManager.loadPlugins(servicePlugins))
.to.throw(/Broken plugin/);
})
.finally(() => {
_.unset(process.env, 'SLS_DEBUG');
});
});
afterEach(() => {
mockRequire.stop('ServicePluginMock1');
});

View File

@ -16,7 +16,7 @@ class Service {
this.provider = {
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${([ ~:a-zA-Z0-9._,\\-\\/\\(\\)]+?)}',
variableSyntax: '\\${([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}',
};
this.custom = {};
this.plugins = [];

View File

@ -31,7 +31,7 @@ describe('Service', () => {
expect(serviceInstance.provider).to.deep.equal({
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${([ ~:a-zA-Z0-9._,\\-\\/\\(\\)]+?)}',
variableSyntax: '\\${([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}',
});
expect(serviceInstance.custom).to.deep.equal({});
expect(serviceInstance.plugins).to.deep.equal([]);
@ -131,7 +131,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
@ -165,7 +165,7 @@ describe('Service', () => {
expect(serviceInstance.service).to.be.equal('new-service');
expect(serviceInstance.provider.name).to.deep.equal('aws');
expect(serviceInstance.provider.variableSyntax).to.equal(
'\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}'
'\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}'
);
expect(serviceInstance.plugins).to.deep.equal(['testPlugin']);
expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' });
@ -188,7 +188,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
@ -221,7 +221,7 @@ describe('Service', () => {
expect(serviceInstance.service).to.be.equal('new-service');
expect(serviceInstance.provider.name).to.deep.equal('aws');
expect(serviceInstance.provider.variableSyntax).to.equal(
'\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}'
'\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}'
);
expect(serviceInstance.plugins).to.deep.equal(['testPlugin']);
expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' });
@ -244,7 +244,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
@ -277,7 +277,7 @@ describe('Service', () => {
expect(serviceInstance.service).to.be.equal('new-service');
expect(serviceInstance.provider.name).to.deep.equal('aws');
expect(serviceInstance.provider.variableSyntax).to.equal(
'\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}'
'\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}'
);
expect(serviceInstance.plugins).to.deep.equal(['testPlugin']);
expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' });
@ -299,7 +299,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {
@ -712,7 +712,7 @@ describe('Service', () => {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}',
variableSyntax: '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}',
},
plugins: ['testPlugin'],
functions: {

View File

@ -10,7 +10,7 @@ const fileExistsSync = require('../utils/fs/fileExistsSync');
const writeFileSync = require('../utils/fs/writeFileSync');
const readFileSync = require('../utils/fs/readFileSync');
const walkDirSync = require('../utils/fs/walkDirSync');
const isDockerContainer = require('../utils/isDockerContainer');
const isDockerContainer = require('is-docker');
const version = require('../../package.json').version;
const segment = require('../utils/segment');
const configUtils = require('../utils/config');
@ -256,7 +256,7 @@ class Utils {
}
let hasCustomVariableSyntaxDefined = false;
const defaultVariableSyntax = '\\${([ ~:a-zA-Z0-9._,\\-\\/\\(\\)]+?)}';
const defaultVariableSyntax = '\\${([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}';
// check if the variableSyntax in the provider section is defined
if (provider && provider.variableSyntax

View File

@ -10,21 +10,15 @@ const testUtils = require('../../tests/utils');
const configUtils = require('../utils/config');
const serverlessVersion = require('../../package.json').version;
const segment = require('../utils/segment');
const proxyquire = require('proxyquire');
chai.use(require('chai-as-promised'));
const expect = require('chai').expect;
const Utils = require('../../lib/classes/Utils');
describe('Utils', () => {
let utils;
let serverless;
let isDockerContainerStub;
let Utils;
beforeEach(() => {
isDockerContainerStub = sinon.stub().returns(true);
Utils = proxyquire('../../lib/classes/Utils.js', {
'../utils/isDockerContainer': isDockerContainerStub,
});
serverless = new Serverless();
utils = new Utils(serverless);
serverless.init();
@ -363,22 +357,6 @@ describe('Utils', () => {
});
});
it('should be able to detect Docker containers', () => {
getConfigStub.returns({
trackingDisabled: false,
frameworkId: '1234wasd',
});
return expect(utils.logStat(serverless)).to.be.fulfilled.then(() => {
expect(getConfigStub.calledOnce).to.equal(true);
expect(isDockerContainerStub.calledOnce).to.equal(true);
expect(trackStub.calledOnce).to.equal(true);
const data = trackStub.args[0][0];
expect(data.properties.general.isDockerContainer).to.equal(true);
});
});
it('should be able to detect IAM Authorizers using the authorizer string format', () => {
getConfigStub.returns({
trackingDisabled: false,

View File

@ -19,7 +19,8 @@ class Variables {
this.optRefSyntax = RegExp(/^opt:/g);
this.selfRefSyntax = RegExp(/^self:/g);
this.cfRefSyntax = RegExp(/^cf:/g);
this.s3RefSynax = RegExp(/^s3:(.+?)\/(.+)$/);
this.s3RefSyntax = RegExp(/^s3:(.+?)\/(.+)$/);
this.stringRefSynax = RegExp(/('.*')|(".*")/g);
}
loadVariableSyntax() {
@ -174,8 +175,10 @@ class Variables {
return this.getValueFromFile(variableString);
} else if (variableString.match(this.cfRefSyntax)) {
return this.getValueFromCf(variableString);
} else if (variableString.match(this.s3RefSynax)) {
} else if (variableString.match(this.s3RefSyntax)) {
return this.getValueFromS3(variableString);
} else if (variableString.match(this.stringRefSynax)) {
return this.getValueFromString(variableString);
}
const errorMessage = [
`Invalid variable reference syntax for variable ${variableString}.`,
@ -196,6 +199,11 @@ class Variables {
return BbPromise.resolve(valueToPopulate);
}
getValueFromString(variableString) {
const valueToPopulate = variableString.replace(/'/g, '');
return BbPromise.resolve(valueToPopulate);
}
getValueFromOptions(variableString) {
const requestedOption = variableString.split(':')[1];
let valueToPopulate;
@ -325,7 +333,7 @@ class Variables {
}
getValueFromS3(variableString) {
const groups = variableString.match(this.s3RefSynax);
const groups = variableString.match(this.s3RefSyntax);
const bucket = groups[1];
const key = groups[2];
return this.serverless.getProvider('aws')

View File

@ -33,7 +33,7 @@ describe('Variables', () => {
it('should set variableSyntax', () => {
const serverless = new Serverless();
serverless.service.provider.variableSyntax = '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}';
serverless.service.provider.variableSyntax = '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}';
serverless.variables.loadVariableSyntax();
expect(serverless.variables.variableSyntax).to.be.a('RegExp');
@ -56,7 +56,7 @@ describe('Variables', () => {
it('should use variableSyntax', () => {
const serverless = new Serverless();
const variableSyntax = '\\${{([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}}';
const variableSyntax = '\\${{([ ~:a-zA-Z0-9._\'",\\-\\/\\(\\)]+?)}}';
const fooValue = '${clientId()}';
const barValue = 'test';
@ -157,6 +157,50 @@ describe('Variables', () => {
});
});
it('should allow a single-quoted string if overwrite syntax provided', () => {
const serverless = new Serverless();
const property = "my stage is ${opt:stage, 'prod'}";
serverless.variables.loadVariableSyntax();
const overwriteStub = sinon
.stub(serverless.variables, 'overwrite').resolves('\'prod\'');
const populateVariableStub = sinon
.stub(serverless.variables, 'populateVariable').resolves('my stage is prod');
return serverless.variables.populateProperty(property).then(newProperty => {
expect(overwriteStub.called).to.equal(true);
expect(populateVariableStub.called).to.equal(true);
expect(newProperty).to.equal('my stage is prod');
serverless.variables.overwrite.restore();
serverless.variables.populateVariable.restore();
return BbPromise.resolve();
});
});
it('should allow a double-quoted string if overwrite syntax provided', () => {
const serverless = new Serverless();
const property = 'my stage is ${opt:stage, "prod"}';
serverless.variables.loadVariableSyntax();
const overwriteStub = sinon
.stub(serverless.variables, 'overwrite').resolves('\'prod\'');
const populateVariableStub = sinon
.stub(serverless.variables, 'populateVariable').resolves('my stage is prod');
return serverless.variables.populateProperty(property).then(newProperty => {
expect(overwriteStub.called).to.equal(true);
expect(populateVariableStub.called).to.equal(true);
expect(newProperty).to.equal('my stage is prod');
serverless.variables.overwrite.restore();
serverless.variables.populateVariable.restore();
return BbPromise.resolve();
});
});
it('should call getValueFromSource if no overwrite syntax provided', () => {
const serverless = new Serverless();
const property = 'my stage is ${opt:stage}';

View File

@ -1,5 +1,6 @@
{
"plugins": [
"./run/index.js",
"./config/config.js",
"./create/create.js",
"./install/install.js",
@ -15,6 +16,7 @@
"./rollback/index.js",
"./slstats/slstats.js",
"./plugin/plugin.js",
"./emit/index.js",
"./aws/configCredentials/awsConfigCredentials.js",
"./aws/provider/awsProvider.js",
"./aws/common/index.js",

View File

@ -1,9 +1,12 @@
'use strict';
const BbPromise = require('bluebird');
const constants = require('constants');
const path = require('path');
const fs = require('fs');
const fse = require('fs-extra');
const os = require('os');
const _ = require('lodash');
class AwsConfigCredentials {
constructor(serverless, options) {
@ -35,12 +38,25 @@ class AwsConfigCredentials {
usage: 'Name of the profile you wish to create. Defaults to "default"',
shortcut: 'n',
},
overwrite: {
usage: 'Overwrite the existing profile configuration in the credentials file',
shortcut: 'o',
},
},
},
},
},
};
if (!os.homedir()) {
throw new this.serverless.classes
.Error('Can\'t find home directory on your local file system.');
}
this.credentialsFilePath = path.join(os.homedir(), '.aws', 'credentials');
// Create the credentials file alongside the .aws directory if it's not yet present
fse.ensureFileSync(this.credentialsFilePath);
this.hooks = {
'config:credentials:config': () => BbPromise.bind(this)
.then(this.configureCredentials),
@ -63,45 +79,104 @@ class AwsConfigCredentials {
}
this.serverless.cli.log('Setting up AWS...');
this.serverless.cli.log('Saving your AWS profile in "~/.aws/credentials"...');
if (!os.homedir()) {
throw new this.serverless.classes
.Error('Can\'t find home directory on your local file system.');
}
this.credentials = this.getCredentials();
// check if ~/.aws/credentials exists
const configDir = path.join(os.homedir(), '.aws');
const credsPath = path.join(configDir, 'credentials');
// Get the profile start line and end line numbers inside the credentials array
const profileBoundaries = this.getProfileBoundaries();
if (this.serverless.utils.fileExistsSync(credsPath)) {
// check if credentials files contains anything
const credsFile = this.serverless.utils.readFileSync(credsPath);
// if credentials file exists w/ profile, exit
if (credsFile.length && credsFile.indexOf(`[${this.options.profile}]`) > -1) {
this.serverless.cli.log(
`Failed! ~/.aws/credentials exists and already has a "${this.options.profile}" profile.`);
// Check if the profile exists
const isNewProfile = profileBoundaries.start === -1;
if (isNewProfile) {
this.addProfile();
} else {
// Only update the profile if the overwrite flag was set
if (!this.options.overwrite) {
const message = [
`Failed! ~/.aws/credentials already has a "${this.options.profile}" profile.`,
' Use the overwrite flag ("-o" or "--overwrite") to force the update',
].join('');
this.serverless.cli.log(message);
return BbPromise.resolve();
}
} else {
// create the credentials file alongside the .aws directory if it's not yet present
fse.ensureFileSync(credsPath);
this.updateProfile(profileBoundaries);
}
// write credentials file with 'default' profile
this.serverless.utils.appendFileSync(
credsPath,
`[${this.options.profile}]
aws_access_key_id=${this.options.key}
aws_secret_access_key=${this.options.secret}
`); // Keep line break at the end. Otherwise will break AWS CLI.
this.serverless.cli.log(
`Success! Your AWS access keys were stored under the "${this.options.profile}" profile.`);
return BbPromise.resolve();
return this.saveCredentialsFile();
}
getCredentials() {
// Get the credentials file lines
const credentialsFileContent = this.serverless.utils.readFileSync(this.credentialsFilePath);
return credentialsFileContent ? credentialsFileContent.split('\n') : [];
}
addProfile() {
this.credentials.push(`[${this.options.profile}]`,
`aws_access_key_id = ${this.options.key}`,
`aws_secret_access_key = ${this.options.secret}`);
}
updateProfile(profileBoundries) {
let currentLine = profileBoundries.start;
let endLine = profileBoundries.end;
// Remove existing 'aws_access_key_id' and 'aws_secret_access_key' properties
while (currentLine < endLine) {
const line = this.credentials[currentLine];
if (
line.indexOf('aws_access_key_id') > -1 ||
line.indexOf('aws_secret_access_key') > -1
) {
this.credentials.splice(currentLine, 1);
endLine--;
} else {
currentLine++;
}
}
// Add the key and the secret to the beginning of the section
const keyLine = `aws_access_key_id = ${this.options.key}`;
const secretLine = `aws_secret_access_key = ${this.options.secret}`;
this.credentials.splice(profileBoundries.start + 1, 0, secretLine);
this.credentials.splice(profileBoundries.start + 1, 0, keyLine);
}
saveCredentialsFile() {
// Generate the file content and add a line break at the end
const updatedCredsFileContent = `${this.credentials.join('\n')}\n`;
this.serverless.cli.log('Saving your AWS profile in "~/.aws/credentials"...');
return this.serverless.utils.writeFile(this.credentialsFilePath, updatedCredsFileContent)
.then(() => {
// set file permissions to only readable/writable by owner (equivalent to 'chmod 600')
// NOTE: `chmod` doesn't behave as intended on Windows, so skip if we're on Windows.
if (os.platform() !== 'win32') {
fs.chmodSync(
this.credentialsFilePath,
(fs.constants || constants).S_IRUSR | (fs.constants || constants).S_IWUSR
);
}
this.serverless.cli.log(
`Success! Your AWS access keys were stored under the "${this.options.profile}" profile.`);
});
}
getProfileBoundaries() {
// Get the line number of the aws profile definition, defaults to -1
const start = this.credentials.indexOf(`[${this.options.profile}]`);
const nextProfile = _.findIndex(this.credentials, line => /\[[^\]]+\]/.test(line), start + 1);
// Get the line number of the next aws profile definition, defaults to the file lines number
const end = nextProfile + 1 || this.credentials.length;
return { start, end };
}
}
module.exports = AwsConfigCredentials;

View File

@ -2,6 +2,7 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const constants = require('constants');
const fs = require('fs');
const fse = require('fs-extra');
const os = require('os');
@ -12,9 +13,24 @@ const Serverless = require('../../../Serverless');
describe('AwsConfigCredentials', () => {
let awsConfigCredentials;
let credentialsFileContent;
let credentialsFilePath;
let serverless;
let sandbox;
let tmpDirPath;
beforeEach(() => {
sandbox = sinon.sandbox.create();
tmpDirPath = testUtils.getTmpDirPath();
credentialsFilePath = path.join(tmpDirPath, '.aws', 'credentials');
credentialsFileContent = '[my-profile]\n';
credentialsFileContent += 'aws_access_key_id = my-old-profile-key\n';
credentialsFileContent += 'aws_secret_access_key = my-old-profile-secret\n';
// stub homedir handler to return the tmpDirPath
sandbox.stub(os, 'homedir').returns(tmpDirPath);
serverless = new Serverless();
serverless.init();
const options = {
@ -25,6 +41,10 @@ describe('AwsConfigCredentials', () => {
awsConfigCredentials = new AwsConfigCredentials(serverless, options);
});
afterEach(() => {
sandbox.restore();
});
describe('#constructor()', () => {
it('should have the command "config"', () => {
expect(awsConfigCredentials.commands.config).to.not.equal(undefined);
@ -66,29 +86,24 @@ describe('AwsConfigCredentials', () => {
awsConfigCredentials.configureCredentials.restore();
});
});
it('should throw an error if the home directory was not found', () => {
os.homedir.returns(null);
expect(() => new AwsConfigCredentials(serverless, {})).to.throw(Error);
});
it('should create the .aws/credentials file if not yet present', () => {
// remove the .aws directory which was created in the before hook of the test
const awsDirectoryPath = path.join(tmpDirPath, '.aws');
fse.removeSync(awsDirectoryPath);
awsConfigCredentials = new AwsConfigCredentials(serverless, {});
const isCredentialsFilePresent = fs.existsSync(path.join(awsDirectoryPath, 'credentials'));
expect(isCredentialsFilePresent).to.equal(true);
});
});
describe('#configureCredentials()', () => {
let homeDir;
let tmpDirPath;
let credentialsFilePath;
beforeEach(() => {
// create a new tmpDir for the homeDir path
tmpDirPath = testUtils.getTmpDirPath();
fse.mkdirsSync(tmpDirPath);
// create the .aws/credetials directory and file
credentialsFilePath = path.join(tmpDirPath, '.aws', 'credentials');
fse.ensureFileSync(credentialsFilePath);
// save the homeDir so that we can reset this later on
homeDir = os.homedir();
process.env.HOME = tmpDirPath;
process.env.HOMEPATH = tmpDirPath;
process.env.USERPROFILE = tmpDirPath;
});
it('should lowercase the provider option', () => {
awsConfigCredentials.options.provider = 'SOMEPROVIDER';
@ -116,11 +131,75 @@ describe('AwsConfigCredentials', () => {
expect(() => awsConfigCredentials.configureCredentials()).to.throw(Error);
});
it('should resolve if profile is already given in credentials file', (done) => {
it('should not update the profile if the overwrite flag is not set', () => {
awsConfigCredentials.options.profile = 'my-profile';
serverless.utils.appendFileSync(credentialsFilePath, '[my-profile]');
awsConfigCredentials.options.key = 'my-new-profile-key';
awsConfigCredentials.options.secret = 'my-new-profile-secret';
awsConfigCredentials.configureCredentials().then(() => done());
fse.outputFileSync(credentialsFilePath, credentialsFileContent);
return awsConfigCredentials.configureCredentials();
});
it('should update the profile', () => {
awsConfigCredentials.options.profile = 'my-profile';
awsConfigCredentials.options.key = 'my-new-profile-key';
awsConfigCredentials.options.secret = 'my-new-profile-secret';
awsConfigCredentials.options.overwrite = true;
fse.outputFileSync(credentialsFilePath, credentialsFileContent);
return awsConfigCredentials.configureCredentials().then(() => {
const UpdatedCredentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
const lineByLineContent = UpdatedCredentialsFileContent.split('\n');
expect(lineByLineContent[0]).to.equal('[my-profile]');
expect(lineByLineContent[1]).to.equal('aws_access_key_id = my-new-profile-key');
expect(lineByLineContent[2]).to.equal('aws_secret_access_key = my-new-profile-secret');
});
});
it('should not alter other profiles when updating a profile', () => {
awsConfigCredentials.options.profile = 'my-profile';
awsConfigCredentials.options.key = 'my-new-profile-key';
awsConfigCredentials.options.secret = 'my-new-profile-secret';
awsConfigCredentials.options.overwrite = true;
credentialsFileContent += '[my-other-profile]\n';
credentialsFileContent += 'aws_secret_access_key = my-other-profile-secret\n';
fse.outputFileSync(credentialsFilePath, credentialsFileContent);
return awsConfigCredentials.configureCredentials().then(() => {
const UpdatedCredentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
const lineByLineContent = UpdatedCredentialsFileContent.split('\n');
expect(lineByLineContent[0]).to.equal('[my-profile]');
expect(lineByLineContent[1]).to.equal('aws_access_key_id = my-new-profile-key');
expect(lineByLineContent[2]).to.equal('aws_secret_access_key = my-new-profile-secret');
expect(lineByLineContent[4]).to.equal('aws_secret_access_key = my-other-profile-secret');
});
});
it('should add the missing credentials to the updated profile', () => {
credentialsFileContent = '[my-profile]\n';
credentialsFileContent += 'aws_secret_access_key = my-profile-secret\n';
awsConfigCredentials.options.profile = 'my-profile';
awsConfigCredentials.options.key = 'my-new-profile-key';
awsConfigCredentials.options.secret = 'my-new-profile-secret';
awsConfigCredentials.options.overwrite = true;
fse.outputFileSync(credentialsFilePath, credentialsFileContent);
return awsConfigCredentials.configureCredentials().then(() => {
const UpdatedCredentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
const lineByLineContent = UpdatedCredentialsFileContent.split('\n');
expect(lineByLineContent[0]).to.equal('[my-profile]');
expect(lineByLineContent[1]).to.equal('aws_access_key_id = my-new-profile-key');
expect(lineByLineContent[2]).to.equal('aws_secret_access_key = my-new-profile-secret');
});
});
it('should append the profile to the credentials file', () => {
@ -129,32 +208,85 @@ describe('AwsConfigCredentials', () => {
awsConfigCredentials.options.secret = 'my-profile-secret';
return awsConfigCredentials.configureCredentials().then(() => {
const credentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
const lineByLineContent = credentialsFileContent.split('\n');
const UpdatedCredentialsFileContent = fs.readFileSync(credentialsFilePath).toString();
const lineByLineContent = UpdatedCredentialsFileContent.split('\n');
expect(lineByLineContent[0]).to.equal('[my-profile]');
expect(lineByLineContent[1]).to.equal('aws_access_key_id=my-profile-key');
expect(lineByLineContent[2]).to.equal('aws_secret_access_key=my-profile-secret');
expect(lineByLineContent[1]).to.equal('aws_access_key_id = my-profile-key');
expect(lineByLineContent[2]).to.equal('aws_secret_access_key = my-profile-secret');
});
});
it('should create the .aws/credentials file if not yet present', () => {
// remove the .aws directory which was created in the before hook of the test
const awsDirectoryPath = path.join(tmpDirPath, '.aws');
fse.removeSync(awsDirectoryPath);
if (os.platform() !== 'win32') {
it('should set the permissions of the credentials file to be owner-only read/write', () =>
awsConfigCredentials.configureCredentials().then(() => {
const fileMode = fs.statSync(credentialsFilePath).mode;
const filePermissions = fileMode & ~(fs.constants || constants).S_IFMT;
return awsConfigCredentials.configureCredentials().then(() => {
const isCredentialsFilePresent = fs.existsSync(path.join(awsDirectoryPath, 'credentials'));
const readableByOwnerPermission = (fs.constants || constants).S_IRUSR;
const writableByOwnerPermission = (fs.constants || constants).S_IWUSR;
const expectedFilePermissions = readableByOwnerPermission | writableByOwnerPermission;
expect(isCredentialsFilePresent).to.equal(true);
});
expect(filePermissions).to.equal(expectedFilePermissions);
})
);
}
});
describe('#getCredentials()', () => {
it('should load credentials file and return the credentials lines', () => {
fse.outputFileSync(credentialsFilePath, credentialsFileContent);
const credentials = awsConfigCredentials.getCredentials();
expect(credentials[0]).to.equal('[my-profile]');
expect(credentials[1]).to.equal('aws_access_key_id = my-old-profile-key');
});
afterEach(() => {
// recover the homeDir
process.env.HOME = homeDir;
process.env.HOMEPATH = homeDir;
process.env.USERPROFILE = homeDir;
it('should return an empty array if the file is empty', () => {
const credentials = awsConfigCredentials.getCredentials();
expect(credentials.length).to.equal(0);
});
});
describe('#getProfileBoundaries()', () => {
it('should return the start and end numbers of the profile', () => {
awsConfigCredentials.options.profile = 'my-profile';
awsConfigCredentials.credentials = [
'[my-profile]',
'aws_access_key_id = my-other-profile-key',
];
const profileBoundaries = awsConfigCredentials.getProfileBoundaries();
expect(profileBoundaries.start).to.equal(0);
expect(profileBoundaries.end).to.equal(2);
});
it('should set the start property to -1 if the profile was not found', () => {
awsConfigCredentials.options.profile = 'my-not-yet-saved-profile';
awsConfigCredentials.credentials = [
'[my-profile]',
'aws_access_key_id = my-other-profile-key',
];
const profileBoundaries = awsConfigCredentials.getProfileBoundaries();
expect(profileBoundaries.start).to.equal(-1);
});
it('should set the end to the credentials length if no other profile was found', () => {
awsConfigCredentials.options.profile = 'my-profile';
awsConfigCredentials.credentials = [
'[my-profile]',
'aws_access_key_id = my-other-profile-key',
'# a comment',
'aws_secret_access_key = my-profile-secret',
];
const profileBoundaries = awsConfigCredentials.getProfileBoundaries();
expect(profileBoundaries.end).to.equal(4);
});
});
});

View File

@ -335,7 +335,7 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
'my-service/.serverless/my-service.zip'
path.join('my-service/.serverless/my-service.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(undefined);
});
@ -369,7 +369,7 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
'my-service/.serverless/my-service.zip'
path.join('my-service/.serverless/my-service.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(undefined);
});
@ -405,10 +405,10 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
'my-service/.serverless/func1.zip'
path.join('my-service/.serverless/func1.zip')
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
'my-service/.serverless/func2.zip'
path.join('my-service/.serverless/func2.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(undefined);
});
@ -442,7 +442,7 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
'my-service/.serverless/my-service.zip'
path.join('my-service/.serverless/my-service.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(true);
});
@ -479,10 +479,10 @@ describe('checkForChanges', () => {
}
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
'my-service/.serverless/func1.zip'
path.join('my-service/.serverless/func1.zip')
);
expect(readFileSyncStub).to.have.been.calledWithExactly(
'my-service/.serverless/func2.zip'
path.join('my-service/.serverless/func2.zip')
);
expect(awsDeploy.serverless.service.provider.shouldNotDeploy).to.equal(true);
});

View File

@ -92,22 +92,32 @@ class AwsDeployList {
}).then((result) => _.map(result, (item) => item.Configuration));
}
getFunctionPaginatedVersions(params, totalVersions) {
return this.provider.request('Lambda',
'listVersionsByFunction',
params,
this.options.stage,
this.options.region)
.then((response) => {
const Versions = (totalVersions || []).concat(response.Versions);
if (response.NextMarker) {
return this.getFunctionPaginatedVersions(
Object.assign({}, params, { Marker: response.NextMarker }), Versions);
}
return Promise.resolve({ Versions });
});
}
getFunctionVersions(funcs) {
const requestPromises = [];
funcs.forEach((func) => {
const params = {
FunctionName: func.FunctionName,
MaxItems: 5,
};
const request = this.provider.request('Lambda',
'listVersionsByFunction',
params,
this.options.stage,
this.options.region);
requestPromises.push(request);
requestPromises.push(this.getFunctionPaginatedVersions(params));
});
return BbPromise.all(requestPromises);
@ -125,7 +135,8 @@ class AwsDeployList {
name = name.replace(`${this.options.stage}-`, '');
message += `${name}: `;
const versions = func.Versions.map((funcEntry) => funcEntry.Version).reverse();
const versions = func.Versions.map((funcEntry) => funcEntry.Version)
.slice(Math.max(0, func.Versions.length - 5));
message += versions.join(', ');
this.serverless.cli.log(message);

View File

@ -163,6 +163,47 @@ describe('AwsDeployList', () => {
});
});
describe('#getFunctionPaginatedVersions()', () => {
beforeEach(() => {
sinon
.stub(awsDeployList.provider, 'request')
.onFirstCall()
.resolves({
Versions: [
{ FunctionName: 'listDeployments-dev-func', Version: '1' },
],
NextMarker: '123',
})
.onSecondCall()
.resolves({
Versions: [
{ FunctionName: 'listDeployments-dev-func', Version: '2' },
],
});
});
afterEach(() => {
awsDeployList.provider.request.restore();
});
it('should return the versions for the provided function when response is paginated', () => {
const params = {
FunctionName: 'listDeployments-dev-func',
};
return awsDeployList.getFunctionPaginatedVersions(params).then((result) => {
const expectedResult = {
Versions: [
{ FunctionName: 'listDeployments-dev-func', Version: '1' },
{ FunctionName: 'listDeployments-dev-func', Version: '2' },
],
};
expect(result).to.deep.equal(expectedResult);
});
});
});
describe('#getFunctionVersions()', () => {
let listVersionsByFunctionStub;
@ -210,13 +251,17 @@ describe('AwsDeployList', () => {
const funcs = [
{
Versions: [
{ FunctionName: 'listDeployments-dev-func-1', Version: '$LATEST' },
{ FunctionName: 'listDeployments-dev-func-1', Version: '1337' },
],
},
{
Versions: [
{ FunctionName: 'listDeployments-dev-func-2', Version: '$LATEST' },
{ FunctionName: 'listDeployments-dev-func-2', Version: '4711' },
{ FunctionName: 'listDeployments-dev-func-2', Version: '2' },
{ FunctionName: 'listDeployments-dev-func-2', Version: '3' },
{ FunctionName: 'listDeployments-dev-func-2', Version: '4' },
{ FunctionName: 'listDeployments-dev-func-2', Version: '5' },
{ FunctionName: 'listDeployments-dev-func-2', Version: '6' },
{ FunctionName: 'listDeployments-dev-func-2', Version: '7' },
],
},
];
@ -229,8 +274,8 @@ describe('AwsDeployList', () => {
.to.be.equal(true);
expect(log.calledWithExactly('-------------')).to.be.equal(true);
expect(log.calledWithExactly('func-1: $LATEST')).to.be.equal(true);
expect(log.calledWithExactly('func-2: 4711, $LATEST')).to.be.equal(true);
expect(log.calledWithExactly('func-1: 1337')).to.be.equal(true);
expect(log.calledWithExactly('func-2: 3, 4, 5, 6, 7')).to.be.equal(true);
});
});
});

View File

@ -11,7 +11,8 @@ module.exports = {
message += `${chalk.yellow.underline('Service Information')}\n`;
message += `${chalk.yellow('service:')} ${info.service}\n`;
message += `${chalk.yellow('stage:')} ${info.stage}\n`;
message += `${chalk.yellow('region:')} ${info.region}`;
message += `${chalk.yellow('region:')} ${info.region}\n`;
message += `${chalk.yellow('stack:')} ${info.stack}`;
this.serverless.cli.consoleLog(message);
return message;

View File

@ -28,6 +28,7 @@ describe('#display()', () => {
service: 'my-first',
stage: 'dev',
region: 'eu-west-1',
stack: 'my-first-dev',
endpoint: null,
functions: [],
apiKeys: [],
@ -46,7 +47,8 @@ describe('#display()', () => {
expectedMessage += `${chalk.yellow.underline('Service Information')}\n`;
expectedMessage += `${chalk.yellow('service:')} my-first\n`;
expectedMessage += `${chalk.yellow('stage:')} dev\n`;
expectedMessage += `${chalk.yellow('region:')} eu-west-1`;
expectedMessage += `${chalk.yellow('region:')} eu-west-1\n`;
expectedMessage += `${chalk.yellow('stack:')} my-first-dev`;
const message = awsInfo.displayServiceInfo();
expect(consoleLogStub.calledOnce).to.equal(true);

View File

@ -12,6 +12,7 @@ module.exports = {
service: this.serverless.service.service,
stage: this.options.stage,
region: this.options.region,
stack: this.provider.naming.getStackName(this.options.stage),
},
outputs: [],
};

View File

@ -86,6 +86,7 @@ describe('#getStackInfo()', () => {
service: 'my-service',
stage: 'dev',
region: 'us-east-1',
stack: 'my-service-dev',
},
outputs: [
{
@ -134,6 +135,7 @@ describe('#getStackInfo()', () => {
service: 'my-service',
stage: 'dev',
region: 'us-east-1',
stack: 'my-service-dev',
},
outputs: [],
};

View File

@ -55,7 +55,9 @@ class AwsInvoke {
}
}).then(() => {
try {
this.options.data = JSON.parse(this.options.data);
if (!this.options.raw) {
this.options.data = JSON.parse(this.options.data);
}
} catch (exception) {
// do nothing if it's a simple string or object already
}

View File

@ -105,6 +105,15 @@ describe('AwsInvoke', () => {
});
});
it('should skip parsing data if "raw" requested', () => {
awsInvoke.options.data = '{"key": "value"}';
awsInvoke.options.raw = true;
return awsInvoke.extendedValidate().then(() => {
expect(awsInvoke.options.data).to.deep.equal('{"key": "value"}');
});
});
it('it should parse file if relative file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
const data = {

View File

@ -0,0 +1,11 @@
from time import sleep
def withRemainingTime(event, context):
start = context.get_remaining_time_in_millis()
sleep(0.001)
stop = context.get_remaining_time_in_millis()
return {
"start": start,
"stop": stop
}

View File

@ -20,3 +20,15 @@ module.exports.withMessageByLambdaProxy = (event, context) => {
}),
});
};
module.exports.withRemainingTime = (event, context) => {
const start = context.getRemainingTimeInMillis();
const stopAt = new Date().getTime() + 1;
while (new Date().getTime() < stopAt);
context.done(null, {
start,
stop: context.getRemainingTimeInMillis(),
});
};

View File

@ -25,6 +25,22 @@ class AwsInvokeLocal {
};
}
validateFile(filePath, key) {
const absolutePath = path.isAbsolute(filePath) ?
filePath :
path.join(this.serverless.config.servicePath, filePath);
if (!this.serverless.utils.fileExistsSync(absolutePath)) {
throw new this.serverless.classes.Error('The file you provided does not exist.');
}
if (absolutePath.endsWith('.js')) {
// to support js - export as an input data
this.options[key] = require(absolutePath); // eslint-disable-line global-require
} else {
this.options[key] = this.serverless.utils.readFileSync(absolutePath);
}
}
extendedValidate() {
this.validate();
@ -33,23 +49,14 @@ class AwsInvokeLocal {
this.options.data = this.options.data || '';
return new BbPromise(resolve => {
if (this.options.contextPath) {
this.validateFile(this.options.contextPath, 'context');
}
if (this.options.data) {
resolve();
} else if (this.options.path) {
const absolutePath = path.isAbsolute(this.options.path) ?
this.options.path :
path.join(this.serverless.config.servicePath, this.options.path);
if (!this.serverless.utils.fileExistsSync(absolutePath)) {
throw new this.serverless.classes.Error('The file you provided does not exist.');
}
//
if (absolutePath.endsWith('.js')) {
// to support js - export as an input data
this.options.data = require(absolutePath); // eslint-disable-line global-require
} else {
this.options.data = this.serverless.utils.readFileSync(absolutePath);
}
this.validateFile(this.options.path, 'data');
resolve();
} else {
@ -65,7 +72,10 @@ class AwsInvokeLocal {
}
}).then(() => {
try {
this.options.data = JSON.parse(this.options.data);
if (!this.options.raw) {
this.options.data = JSON.parse(this.options.data);
this.options.context = JSON.parse(this.options.context);
}
} catch (exception) {
// do nothing if it's a simple string or object already
}
@ -79,7 +89,6 @@ class AwsInvokeLocal {
|| 1024;
const lambdaDefaultEnvVars = {
PATH: '/usr/local/lib64/node-v4.3.x/bin:/usr/local/bin:/usr/bin/:/bin',
LANG: 'en_US.UTF-8',
LD_LIBRARY_PATH: '/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib', // eslint-disable-line max-len
LAMBDA_TASK_ROOT: '/var/task',
@ -114,37 +123,45 @@ class AwsInvokeLocal {
return this.invokeLocalNodeJs(
handlerPath,
handlerName,
this.options.data);
this.options.data,
this.options.context);
}
if (runtime === 'python2.7' || runtime === 'python3.6') {
return this.invokeLocalPython(
runtime,
process.platform === 'win32' ? 'python.exe' : runtime,
handlerPath,
handlerName,
this.options.data);
this.options.data,
this.options.context);
}
throw new this.serverless.classes
.Error('You can only invoke Node.js & Python functions locally.');
}
invokeLocalPython(runtime, handlerPath, handlerName, event) {
invokeLocalPython(runtime, handlerPath, handlerName, event, context) {
const input = JSON.stringify({
event: event || {},
context,
});
if (process.env.VIRTUAL_ENV) {
process.env.PATH = `${process.env.VIRTUAL_ENV}/bin:${process.env.PATH}`;
}
return new BbPromise(resolve => {
const python = spawn(runtime,
[path.join(__dirname, 'invoke.py'), handlerPath, handlerName], { env: process.env });
python.stdout.on('data', (buf) => this.serverless.cli.consoleLog(buf.toString()));
python.stderr.on('data', (buf) => this.serverless.cli.consoleLog(buf.toString()));
python.stdin.write(JSON.stringify(event || {}));
python.stdin.write(input);
python.stdin.end();
python.on('close', () => resolve());
});
}
invokeLocalNodeJs(handlerPath, handlerName, event) {
invokeLocalNodeJs(handlerPath, handlerName, event, customContext) {
let lambda;
try {
@ -201,7 +218,10 @@ class AwsInvokeLocal {
const startTime = new Date();
const context = {
const timeout = Number(this.options.functionObj.timeout)
|| Number(this.serverless.service.provider.timeout)
|| 6;
let context = {
awsRequestId: 'id',
invokeid: 'id',
logGroupName: this.provider.naming.getLogGroupName(this.options.functionObj.name),
@ -222,10 +242,14 @@ class AwsInvokeLocal {
return callback(error, result);
},
getRemainingTimeInMillis() {
return (new Date()).valueOf() - startTime.valueOf();
return Math.max((timeout * 1000) - ((new Date()).valueOf() - startTime.valueOf()), 0);
},
};
if (customContext) {
context = customContext;
}
return lambda(event, context, callback);
}
}

View File

@ -106,6 +106,15 @@ describe('AwsInvokeLocal', () => {
});
});
it('should skip parsing data if "raw" requested', () => {
awsInvokeLocal.options.data = '{"key": "value"}';
awsInvokeLocal.options.raw = true;
return awsInvokeLocal.extendedValidate().then(() => {
expect(awsInvokeLocal.options.data).to.deep.equal('{"key": "value"}');
});
});
it('it should parse file if relative file path is provided', () => {
serverless.config.servicePath = testUtils.getTmpDirPath();
const data = {
@ -113,10 +122,10 @@ describe('AwsInvokeLocal', () => {
};
serverless.utils.writeFileSync(path
.join(serverless.config.servicePath, 'data.json'), JSON.stringify(data));
awsInvokeLocal.options.path = 'data.json';
awsInvokeLocal.options.contextPath = 'data.json';
return awsInvokeLocal.extendedValidate().then(() => {
expect(awsInvokeLocal.options.data).to.deep.equal(data);
expect(awsInvokeLocal.options.context).to.deep.equal(data);
});
});
@ -130,6 +139,7 @@ describe('AwsInvokeLocal', () => {
const dataFile = path.join(serverless.config.servicePath, 'data.json');
serverless.utils.writeFileSync(dataFile, JSON.stringify(data));
awsInvokeLocal.options.path = dataFile;
awsInvokeLocal.options.contextPath = false;
return awsInvokeLocal.extendedValidate().then(() => {
expect(awsInvokeLocal.options.data).to.deep.equal(data);
@ -226,8 +236,6 @@ describe('AwsInvokeLocal', () => {
it('it should load default lambda env vars', () => awsInvokeLocal
.loadEnvVars().then(() => {
expect(process.env.PATH)
.to.equal('/usr/local/lib64/node-v4.3.x/bin:/usr/local/bin:/usr/bin/:/bin');
expect(process.env.LANG).to.equal('en_US.UTF-8');
expect(process.env.LD_LIBRARY_PATH)
.to.equal('/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib'); // eslint-disable-line max-len
@ -298,7 +306,8 @@ describe('AwsInvokeLocal', () => {
expect(invokeLocalNodeJsStub.calledWithExactly(
'handler',
'hello',
{}
{},
undefined
)).to.be.equal(true);
awsInvokeLocal.invokeLocalNodeJs.restore();
})
@ -318,6 +327,21 @@ describe('AwsInvokeLocal', () => {
});
});
it('should call invokeLocalNodeJs with custom context if provided', () => {
awsInvokeLocal.options.context = 'custom context';
awsInvokeLocal.invokeLocal()
.then(() => {
expect(invokeLocalNodeJsStub.calledOnce).to.be.equal(true);
expect(invokeLocalNodeJsStub.calledWithExactly(
'handler',
'hello',
{},
'custom context'
)).to.be.equal(true);
awsInvokeLocal.invokeLocalNodeJs.restore();
});
});
it('should call invokeLocalPython when python2.7 runtime is set', () => {
awsInvokeLocal.options.functionObj.runtime = 'python2.7';
awsInvokeLocal.invokeLocal()
@ -385,6 +409,37 @@ describe('AwsInvokeLocal', () => {
});
});
describe('context.remainingTimeInMillis', () => {
it('should become lower over time', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withRemainingTime');
const remainingTimes = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
expect(remainingTimes.start).to.be.above(remainingTimes.stop);
});
it('should start with the timeout value', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
awsInvokeLocal.serverless.service.provider.timeout = 5;
awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withRemainingTime');
const remainingTimes = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
expect(remainingTimes.start).to.eql(5000);
});
it('should never become negative', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
awsInvokeLocal.serverless.service.provider.timeout = 0.00001;
awsInvokeLocal.invokeLocalNodeJs('fixture/handlerWithSuccess', 'withRemainingTime');
const remainingTimes = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
expect(remainingTimes.stop).to.eql(0);
});
});
describe('with extraServicePath', () => {
it('should succeed if succeed', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
@ -421,4 +476,37 @@ describe('AwsInvokeLocal', () => {
expect(serverless.cli.consoleLog.lastCall.args[0]).to.contain('"errorMessage": "failed"');
});
});
// Ignored because it fails in CI
// See https://github.com/serverless/serverless/pull/4047#issuecomment-320460285
describe.skip('#invokeLocalPython', () => {
beforeEach(() => {
awsInvokeLocal.options = {
functionObj: {
name: '',
},
};
serverless.cli = new CLI(serverless);
sinon.stub(serverless.cli, 'consoleLog');
});
afterEach(() => {
serverless.cli.consoleLog.restore();
});
describe('context.remainingTimeInMillis', () => {
it('should become lower over time', () => {
awsInvokeLocal.serverless.config.servicePath = __dirname;
return awsInvokeLocal.invokeLocalPython(
'python2.7',
'fixture/handler',
'withRemainingTime').then(() => {
const remainingTimes = JSON.parse(serverless.cli.consoleLog.lastCall.args[0]);
expect(remainingTimes.start).to.be.above(remainingTimes.stop);
});
});
});
});
});

View File

@ -9,9 +9,10 @@ class FakeLambdaContext(object):
self.name = name
self.version = version
self.created = time()
self.timeout = timeout
def get_remaining_time_in_millis(self):
return (self.created - time()) * 1000
return int(max((self.timeout * 1000) - (int(round(time() * 1000)) - int(round(self.created * 1000))), 0))
@property
def function_name(self):
@ -54,6 +55,9 @@ if __name__ == '__main__':
module = import_module(args.handler_path.replace('/', '.'))
handler = getattr(module, args.handler_name)
event = json.load(sys.stdin)
result = handler(event, FakeLambdaContext())
input = json.load(sys.stdin)
context = FakeLambdaContext()
if 'context' in input:
context = input['context']
result = handler(input['event'], context)
sys.stdout.write(json.dumps(result, indent=4))

View File

@ -102,12 +102,13 @@ module.exports = {
// Handle stack create/update/delete failures
if ((stackLatestError && !this.options.verbose)
|| (stackStatus
&& stackStatus.endsWith('ROLLBACK_COMPLETE')
&& (stackStatus.endsWith('ROLLBACK_COMPLETE')
|| stackStatus === 'DELETE_FAILED')
&& this.options.verbose)) {
// empty console.log for a prettier output
if (!this.options.verbose) this.serverless.cli.consoleLog('');
this.serverless.cli.log('Deployment failed!');
let errorMessage = 'An error occurred while provisioning your stack: ';
this.serverless.cli.log('Operation failed!');
let errorMessage = 'An error occurred: ';
errorMessage += `${stackLatestError.LogicalResourceId} - `;
errorMessage += `${stackLatestError.ResourceStatusReason}.`;
return reject(new this.serverless.classes.Error(errorMessage));

View File

@ -467,7 +467,7 @@ describe('monitorStack', () => {
describeStackEventsStub.onCall(3).resolves(updateRollbackComplete);
return awsPlugin.monitorStack('update', cfDataMock, 10).catch((e) => {
let errorMessage = 'An error occurred while provisioning your stack: ';
let errorMessage = 'An error occurred: ';
errorMessage += 'mochaS3 - Bucket already exists.';
expect(e.name).to.be.equal('ServerlessError');
expect(e.message).to.be.equal(errorMessage);
@ -628,7 +628,7 @@ describe('monitorStack', () => {
describeStackEventsStub.onCall(3).resolves(updateRollbackFailedEvent);
return awsPlugin.monitorStack('update', cfDataMock, 10).catch((e) => {
let errorMessage = 'An error occurred while provisioning your stack: ';
let errorMessage = 'An error occurred: ';
errorMessage += 'mochaS3 - Bucket already exists.';
expect(e.name).to.be.equal('ServerlessError');
expect(e.message).to.be.equal(errorMessage);
@ -647,6 +647,168 @@ describe('monitorStack', () => {
});
});
it('should throw an error and exit immediately if stack status is DELETE_FAILED', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.provider, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
const deleteStartEvent = {
StackEvents: [
{
EventId: '1a2b3c4d',
StackName: 'new-service-dev',
LogicalResourceId: 'new-service-dev',
ResourceType: 'AWS::CloudFormation::Stack',
Timestamp: new Date(),
ResourceStatus: 'DELETE_IN_PROGRESS',
},
],
};
const deleteItemEvent = {
StackEvents: [
{
EventId: '1e2f3g4h',
StackName: 'new-service-dev',
LogicalResourceId: 'mochaLambda',
ResourceType: 'AWS::Lambda::Function',
Timestamp: new Date(),
ResourceStatus: 'DELETE_IN_PROGRESS',
},
],
};
const deleteItemFailedEvent = {
StackEvents: [
{
EventId: '1i2j3k4l',
StackName: 'new-service-dev',
LogicalResourceId: 'mochaLambda',
ResourceType: 'AWS::Lambda::Function',
Timestamp: new Date(),
ResourceStatus: 'DELETE_FAILED',
ResourceStatusReason: 'You are not authorized to perform this operation',
},
],
};
const deleteFailedEvent = {
StackEvents: [
{
EventId: '1m2n3o4p',
StackName: 'new-service-dev',
LogicalResourceId: 'new-service-dev',
ResourceType: 'AWS::CloudFormation::Stack',
Timestamp: new Date(),
ResourceStatus: 'DELETE_FAILED',
},
],
};
describeStackEventsStub.onCall(0).resolves(deleteStartEvent);
describeStackEventsStub.onCall(1).resolves(deleteItemEvent);
describeStackEventsStub.onCall(2).resolves(deleteItemFailedEvent);
describeStackEventsStub.onCall(3).resolves(deleteFailedEvent);
return awsPlugin.monitorStack('removal', cfDataMock, 10).catch((e) => {
let errorMessage = 'An error occurred: ';
errorMessage += 'mochaLambda - You are not authorized to perform this operation.';
expect(e.name).to.be.equal('ServerlessError');
expect(e.message).to.be.equal(errorMessage);
// callCount is 2 because Serverless will immediately exits and shows the error
expect(describeStackEventsStub.callCount).to.be.equal(3);
expect(describeStackEventsStub.calledWithExactly(
'CloudFormation',
'describeStackEvents',
{
StackName: cfDataMock.StackId,
},
awsPlugin.options.stage,
awsPlugin.options.region
)).to.be.equal(true);
awsPlugin.provider.request.restore();
});
});
it('should throw an error if stack status is DELETE_FAILED and should output all ' +
'stack events information with the --verbose option', () => {
awsPlugin.options.verbose = true;
const describeStackEventsStub = sinon.stub(awsPlugin.provider, 'request');
const cfDataMock = {
StackId: 'new-service-dev',
};
const deleteStartEvent = {
StackEvents: [
{
EventId: '1a2b3c4d',
StackName: 'new-service-dev',
LogicalResourceId: 'new-service-dev',
ResourceType: 'AWS::CloudFormation::Stack',
Timestamp: new Date(),
ResourceStatus: 'DELETE_IN_PROGRESS',
},
],
};
const deleteItemEvent = {
StackEvents: [
{
EventId: '1e2f3g4h',
StackName: 'new-service-dev',
LogicalResourceId: 'mochaLambda',
ResourceType: 'AWS::Lambda::Function',
Timestamp: new Date(),
ResourceStatus: 'DELETE_IN_PROGRESS',
},
],
};
const deleteItemFailedEvent = {
StackEvents: [
{
EventId: '1i2j3k4l',
StackName: 'new-service-dev',
LogicalResourceId: 'mochaLambda',
ResourceType: 'AWS::Lambda::Function',
Timestamp: new Date(),
ResourceStatus: 'DELETE_FAILED',
ResourceStatusReason: 'You are not authorized to perform this operation',
},
],
};
const deleteFailedEvent = {
StackEvents: [
{
EventId: '1m2n3o4p',
StackName: 'new-service-dev',
LogicalResourceId: 'new-service-dev',
ResourceType: 'AWS::CloudFormation::Stack',
Timestamp: new Date(),
ResourceStatus: 'DELETE_FAILED',
},
],
};
describeStackEventsStub.onCall(0).resolves(deleteStartEvent);
describeStackEventsStub.onCall(1).resolves(deleteItemEvent);
describeStackEventsStub.onCall(2).resolves(deleteItemFailedEvent);
describeStackEventsStub.onCall(3).resolves(deleteFailedEvent);
return awsPlugin.monitorStack('removal', cfDataMock, 10).catch((e) => {
let errorMessage = 'An error occurred: ';
errorMessage += 'mochaLambda - You are not authorized to perform this operation.';
expect(e.name).to.be.equal('ServerlessError');
expect(e.message).to.be.equal(errorMessage);
// callCount is 2 because Serverless will immediately exits and shows the error
expect(describeStackEventsStub.callCount).to.be.equal(4);
expect(describeStackEventsStub.calledWithExactly(
'CloudFormation',
'describeStackEvents',
{
StackName: cfDataMock.StackId,
},
awsPlugin.options.stage,
awsPlugin.options.region
)).to.be.equal(true);
awsPlugin.provider.request.restore();
});
});
it('should record an error and fail if status is UPDATE_ROLLBACK_IN_PROGRESS', () => {
const describeStackEventsStub = sinon.stub(awsPlugin.provider, 'request');
const cfDataMock = {
@ -692,7 +854,7 @@ describe('monitorStack', () => {
describeStackEventsStub.onCall(2).resolves(updateRollbackCompleteEvent);
return awsPlugin.monitorStack('update', cfDataMock, 10).catch((e) => {
let errorMessage = 'An error occurred while provisioning your stack: ';
let errorMessage = 'An error occurred: ';
errorMessage += 'mocha - Export is in use.';
expect(e.name).to.be.equal('ServerlessError');
expect(e.message).to.be.equal(errorMessage);

View File

@ -195,21 +195,19 @@ class AwsProvider {
const result = {};
const stageUpper = this.getStage() ? this.getStage().toUpperCase() : null;
let profile;
if (this.options['aws-profile']) {
profile = this.options['aws-profile'];
} else if (this.serverless.service.provider.profile) {
profile = this.serverless.service.provider.profile;
}
// add specified credentials, overriding with more specific declarations
impl.addCredentials(result, this.serverless.service.provider.credentials); // config creds
impl.addProfileCredentials(result, profile);
if (this.serverless.service.provider.profile) {
// config profile
impl.addProfileCredentials(result, this.serverless.service.provider.profile);
}
impl.addEnvironmentCredentials(result, 'AWS'); // creds for all stages
impl.addEnvironmentProfile(result, 'AWS');
impl.addEnvironmentCredentials(result, `AWS_${stageUpper}`); // stage specific creds
impl.addEnvironmentProfile(result, `AWS_${stageUpper}`);
if (this.options['aws-profile']) {
impl.addProfileCredentials(result, this.options['aws-profile']); // CLI option profile
}
result.region = this.getRegion();
const deploymentBucketObject = this.serverless.service.provider.deploymentBucketObject;

View File

@ -461,6 +461,7 @@ describe('AwsProvider', () => {
});
it('should get credentials when profile is provied via --aws-profile option', () => {
process.env.AWS_PROFILE = 'envDefault';
newAwsProvider.options['aws-profile'] = 'notDefault';
const credentials = newAwsProvider.getCredentials();

View File

@ -5,7 +5,7 @@ const BbPromise = require('bluebird');
module.exports = {
remove() {
this.serverless.cli.log('Removing Stack...');
const stackName = `${this.serverless.service.service}-${this.options.stage}`;
const stackName = this.provider.naming.getStackName();
const params = {
StackName: stackName,
};

View File

@ -9,6 +9,8 @@ const userStats = require('../../utils/userStats');
// class wide constants
const validTemplates = [
'aws-nodejs',
'aws-nodejs-typescript',
'aws-nodejs-ecma-script',
'aws-python',
'aws-python3',
'aws-groovy-gradle',
@ -18,10 +20,12 @@ const validTemplates = [
'aws-csharp',
'aws-fsharp',
'azure-nodejs',
'google-nodejs',
'kubeless-python',
'kubeless-nodejs',
'openwhisk-nodejs',
'openwhisk-python',
'openwhisk-swift',
'google-nodejs',
'plugin',
// this template is used to streamline the onboarding process

View File

@ -99,6 +99,46 @@ describe('Create', () => {
});
});
it('should generate scaffolding for "aws-nodejs-typescript" template', () => {
process.chdir(tmpDir);
create.options.template = 'aws-nodejs-typescript';
return create.create().then(() => {
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'serverless.yml')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'handler.ts')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'tsconfig.json')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'package.json')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'webpack.config.js')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, '.gitignore')))
.to.be.equal(true);
});
});
it('should generate scaffolding for "aws-nodejs-ecma-script" template', () => {
process.chdir(tmpDir);
create.options.template = 'aws-nodejs-ecma-script';
return create.create().then(() => {
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'serverless.yml')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'first.js')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'second.js')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'package.json')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'webpack.config.js')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, '.gitignore')))
.to.be.equal(true);
});
});
it('should generate scaffolding for "aws-csharp" template', () => {
process.chdir(tmpDir);
create.options.template = 'aws-csharp';
@ -387,6 +427,38 @@ describe('Create', () => {
});
});
it('should generate scaffolding for "kubeless-python" template', () => {
process.chdir(tmpDir);
create.options.template = 'kubeless-python';
return create.create().then(() => {
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'package.json')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'serverless.yml')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'handler.py')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, '.gitignore')))
.to.be.equal(true);
});
});
it('should generate scaffolding for "kubeless-nodejs" template', () => {
process.chdir(tmpDir);
create.options.template = 'kubeless-nodejs';
return create.create().then(() => {
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'package.json')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'serverless.yml')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, 'handler.js')))
.to.be.equal(true);
expect(create.serverless.utils.fileExistsSync(path.join(tmpDir, '.gitignore')))
.to.be.equal(true);
});
});
it('should generate scaffolding for "plugin" template', () => {
process.chdir(tmpDir);
create.options.template = 'plugin';

View File

@ -0,0 +1,12 @@
// eslint-disable-next-line import/prefer-default-export
export const hello = (event, context, callback) => {
const p = new Promise((resolve) => {
resolve('success');
});
p
.then(() => callback(null, {
message: 'Go Serverless Webpack (Ecma Script) v1.0! First module!',
event,
}))
.catch(e => callback(e));
};

View File

@ -0,0 +1,9 @@
# package directories
node_modules
jspm_packages
# Serverless directories
.serverless
# Webpack directories
.webpack

View File

@ -0,0 +1,19 @@
{
"name": "aws-nodejs-ecma-script",
"version": "1.0.0",
"description": "Serverless webpack example using ecma script",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.6.0",
"serverless-webpack": "^2.2.0",
"webpack": "^3.3.0"
},
"author": "The serverless webpack authors (https://github.com/elastic-coders/serverless-webpack)",
"license": "MIT"
}

View File

@ -0,0 +1,16 @@
// eslint-disable-next-line import/prefer-default-export
export const hello = (event, context, cb) => {
const p = new Promise((resolve) => {
resolve('success');
});
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'Go Serverless Webpack (Ecma Script) v1.0! Second module!',
input: event,
}),
};
p
.then(() => cb(null, response))
.catch(e => cb(e));
};

View File

@ -0,0 +1,27 @@
service:
name: aws-nodejs-ecma-script
# Add the serverless-webpack plugin
plugins:
- serverless-webpack
provider:
name: aws
runtime: nodejs6.10
functions:
# Example without LAMBDA-PROXY integration
# Invoking locally:
# sls webpack invoke -f first
first:
handler: first.hello
# Example with LAMBDA-PROXY integration
# Invoking locally:
# sls webpack invoke -f second
second:
handler: second.hello
events:
- http:
method: get
path: second
integration: lambda

View File

@ -0,0 +1,21 @@
const path = require('path');
// eslint-disable-next-line import/no-unresolved
const slsw = require('serverless-webpack');
module.exports = {
entry: slsw.lib.entries,
target: 'node',
module: {
loaders: [{
test: /\.js$/,
loaders: ['babel-loader'],
include: __dirname,
exclude: /node_modules/,
}],
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
};

View File

@ -0,0 +1,9 @@
# package directories
node_modules
jspm_packages
# Serverless directories
.serverless
# Webpack directories
.webpack

View File

@ -0,0 +1,3 @@
export const hello = (event, context, cb) => cb(null,
{ message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!', event }
);

View File

@ -0,0 +1,17 @@
{
"name": "aws-nodejs-typescript",
"version": "1.0.0",
"description": "Serverless webpack example using Typescript",
"main": "handler.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"serverless-webpack": "^2.2.0",
"ts-loader": "^2.3.1",
"typescript": "^2.4.2",
"webpack": "^3.3.0"
},
"author": "The serverless webpack authors (https://github.com/elastic-coders/serverless-webpack)",
"license": "MIT"
}

View File

@ -0,0 +1,22 @@
service:
name: aws-nodejs-typescript
# Add the serverless-webpack plugin
plugins:
- serverless-webpack
provider:
name: aws
runtime: nodejs6.10
functions:
# Example with LAMBDA-PROXY integration
# Invoking locally:
# sls webpack invoke -f hello
hello:
handler: handler.hello
events:
- http:
method: get
path: hello
integration: lambda

View File

@ -0,0 +1,5 @@
{
"compilerOptions": {
"sourceMap": true
}
}

View File

@ -0,0 +1,18 @@
const path = require('path');
// eslint-disable-next-line import/no-unresolved
const slsw = require('serverless-webpack');
module.exports = {
entry: slsw.lib.entries,
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
target: 'node',
module: {
loaders: [
{ test: /\.ts(x?)$/, loader: 'ts-loader' },
],
},
};

View File

@ -42,7 +42,7 @@ functions:
authLevel : anonymous
- http: true
x-azure-settings:
diections: out
direction: out
name: res
# The following are a few examples of other events you can configure:

View File

@ -0,0 +1,6 @@
# package directories
node_modules
jspm_packages
# Serverless directories
.serverless

View File

@ -0,0 +1,17 @@
'use strict';
const _ = require('lodash');
module.exports = {
capitalize(req, res) {
let body = [];
req.on('error', (err) => {
console.error(err);
}).on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
res.end(_.capitalize(body));
});
},
};

View File

@ -0,0 +1,19 @@
{
"name": "kubeless-nodejs",
"version": "1.0.0",
"description": "Example function for serverless kubeless",
"dependencies": {
"serverless-kubeless": "^0.1.8",
"lodash": "^4.1.0"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"serverless",
"kubeless"
],
"author": "The Kubeless Authors",
"license": "Apache-2.0"
}

View File

@ -0,0 +1,27 @@
# Welcome to Serverless!
#
# For full config options, check the kubeless plugin docs:
# https://github.com/serverless/serverless-kubeless
#
# For documentation on kubeless itself:
# http://kubeless.io
# Update the service name below with your own service name
service: capitalize
# Please ensure the serverless-kubeless provider plugin is installed globally.
# $ npm install -g serverless-kubeless
#
# ...before installing project dependencies to register this provider.
# $ npm install
provider:
name: kubeless
runtime: nodejs6
plugins:
- serverless-kubeless
functions:
capitalize:
handler: handler.capitalize

View File

@ -0,0 +1,6 @@
# package directories
node_modules
jspm_packages
# Serverless directories
.serverless

View File

@ -0,0 +1,14 @@
import json
def hello(request):
body = {
"message": "Go Serverless v1.0! Your function executed successfully!",
"input": request.json
}
response = {
"statusCode": 200,
"body": json.dumps(body)
}
return response

Some files were not shown because too many files have changed in this diff Show More