mirror of
https://github.com/serverless/serverless.git
synced 2026-01-18 14:58:43 +00:00
fix conflict
This commit is contained in:
commit
388f0e502a
20
.appveyor.yml
Normal file
20
.appveyor.yml
Normal 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
|
||||
@ -2,3 +2,4 @@ coverage
|
||||
node_modules
|
||||
tmp
|
||||
tmpdirs-serverless
|
||||
lib/plugins/create/templates/**
|
||||
|
||||
26
CHANGELOG.md
26
CHANGELOG.md
@ -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)
|
||||
|
||||
@ -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
226
README.md
@ -1,4 +1,4 @@
|
||||
[](http://serverless.com)
|
||||
[](http://serverless.com)
|
||||
|
||||
[](http://www.serverless.com)
|
||||
[](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 -->
|
||||
|
||||
|
||||
@ -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
51
RELEASE_PROCESS.md
Normal 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
1
assets/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
|
||||
BIN
assets/framework_repo.png
Normal file
BIN
assets/framework_repo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@ -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
67
docs/platform/README.md
Normal 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.
|
||||
26
docs/platform/commands/README.md
Normal file
26
docs/platform/commands/README.md
Normal 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.
|
||||
49
docs/platform/commands/emit.md
Normal file
49
docs/platform/commands/emit.md
Normal 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
|
||||
```
|
||||
26
docs/platform/commands/login.md
Normal file
26
docs/platform/commands/login.md
Normal 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
|
||||
```
|
||||
22
docs/platform/commands/logout.md
Normal file
22
docs/platform/commands/logout.md
Normal 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
|
||||
```
|
||||
39
docs/platform/commands/run.md
Normal file
39
docs/platform/commands/run.md
Normal 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`
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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/)
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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/)
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
```
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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}}
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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/)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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/)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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/)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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');
|
||||
});
|
||||
|
||||
@ -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 = [];
|
||||
|
||||
@ -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: {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -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}';
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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: [],
|
||||
};
|
||||
|
||||
@ -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: [],
|
||||
};
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 = {
|
||||
|
||||
0
lib/plugins/aws/invokeLocal/fixture/__init__.py
Normal file
0
lib/plugins/aws/invokeLocal/fixture/__init__.py
Normal file
11
lib/plugins/aws/invokeLocal/fixture/handler.py
Normal file
11
lib/plugins/aws/invokeLocal/fixture/handler.py
Normal 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
|
||||
}
|
||||
@ -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(),
|
||||
});
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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';
|
||||
|
||||
12
lib/plugins/create/templates/aws-nodejs-ecma-script/first.js
Normal file
12
lib/plugins/create/templates/aws-nodejs-ecma-script/first.js
Normal 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));
|
||||
};
|
||||
@ -0,0 +1,9 @@
|
||||
# package directories
|
||||
node_modules
|
||||
jspm_packages
|
||||
|
||||
# Serverless directories
|
||||
.serverless
|
||||
|
||||
# Webpack directories
|
||||
.webpack
|
||||
@ -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"
|
||||
}
|
||||
@ -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));
|
||||
};
|
||||
@ -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
|
||||
@ -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',
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,9 @@
|
||||
# package directories
|
||||
node_modules
|
||||
jspm_packages
|
||||
|
||||
# Serverless directories
|
||||
.serverless
|
||||
|
||||
# Webpack directories
|
||||
.webpack
|
||||
@ -0,0 +1,3 @@
|
||||
export const hello = (event, context, cb) => cb(null,
|
||||
{ message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!', event }
|
||||
);
|
||||
@ -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"
|
||||
}
|
||||
@ -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
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
@ -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' },
|
||||
],
|
||||
},
|
||||
};
|
||||
@ -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:
|
||||
|
||||
6
lib/plugins/create/templates/kubeless-nodejs/gitignore
Normal file
6
lib/plugins/create/templates/kubeless-nodejs/gitignore
Normal file
@ -0,0 +1,6 @@
|
||||
# package directories
|
||||
node_modules
|
||||
jspm_packages
|
||||
|
||||
# Serverless directories
|
||||
.serverless
|
||||
17
lib/plugins/create/templates/kubeless-nodejs/handler.js
Normal file
17
lib/plugins/create/templates/kubeless-nodejs/handler.js
Normal 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));
|
||||
});
|
||||
},
|
||||
};
|
||||
19
lib/plugins/create/templates/kubeless-nodejs/package.json
Normal file
19
lib/plugins/create/templates/kubeless-nodejs/package.json
Normal 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"
|
||||
}
|
||||
27
lib/plugins/create/templates/kubeless-nodejs/serverless.yml
Normal file
27
lib/plugins/create/templates/kubeless-nodejs/serverless.yml
Normal 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
|
||||
6
lib/plugins/create/templates/kubeless-python/gitignore
Normal file
6
lib/plugins/create/templates/kubeless-python/gitignore
Normal file
@ -0,0 +1,6 @@
|
||||
# package directories
|
||||
node_modules
|
||||
jspm_packages
|
||||
|
||||
# Serverless directories
|
||||
.serverless
|
||||
14
lib/plugins/create/templates/kubeless-python/handler.py
Normal file
14
lib/plugins/create/templates/kubeless-python/handler.py
Normal 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
Loading…
x
Reference in New Issue
Block a user