Merge branch 'master' into window-env-path

This commit is contained in:
Rafal Wilinski 2017-09-19 16:04:14 +02:00 committed by GitHub
commit 6e05ce8f9c
47 changed files with 1238 additions and 90 deletions

View File

@ -22,6 +22,8 @@ Serverless is an MIT open-source project, actively maintained by a full-time, ve
## Contents
<img align="right" width="400" src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/email/sls-getting-started.gif" />
* [Quick Start](#quick-start)
* [Examples](https://github.com/serverless/examples)
* [Services](#services)
@ -129,7 +131,7 @@ The following are services you can instantly install and use by running `serverl
## <a name="features"></a>Features
* Supports Node.js, Python, Java & Scala.
* Supports Node.js, Python, Java, Scala, C#, F#, Groovy, Kotlin, PHP & Swift.
* Manages the lifecycle of your serverless architecture (build, deploy, update, delete).
* Safely deploy functions, events and their required resources together via provider resource managers (e.g., AWS CloudFormation).
* Functions can be grouped ("serverless services") for easy management of code, resources & processes, across large projects & teams.
@ -152,40 +154,60 @@ 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 Apigateway Plugin](https://github.com/GFG/serverless-apigateway-plugin)** <br/> Configure the AWS api gateway: Binary support, Headers and Body template mappings | [GFG](http://github.com/GFG) |
| **[Serverless Apigw Binary](https://github.com/maciejtreder/serverless-apigw-binary)** <br/> Plugin to enable binary support in AWS API Gateway. | [maciejtreder](http://github.com/maciejtreder) |
| **[Serverless Apigwy Binary](https://github.com/ryanmurakami/serverless-apigwy-binary)** <br/> Serverless plugin for configuring API Gateway to return binary responses | [ryanmurakami](http://github.com/ryanmurakami) |
| **[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 Cf Vars](https://gitlab.com/kabo/serverless-cf-vars)** <br/> Enables use of AWS pseudo functions and Fn::Sub string substitution | [kabo](http://github.com/kabo) |
| **[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 Custom Packaging Plugin](https://github.com/hypoport/serverless-custom-packaging-plugin)** <br/> Plugin to package your sourcecode using a custom target path inside the zip. | [hypoport](http://github.com/hypoport) |
| **[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 Domain Manager](https://github.com/amplify-education/serverless-domain-manager)** <br/> Serverless plugin for managing custom domains with API Gateways. | [amplify-education](http://github.com/amplify-education) |
| **[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 Autoscaling](https://github.com/sbstjn/serverless-dynamodb-autoscaling)** <br/> Configure Amazon DynamoDB's native Auto Scaling for your table capacities. | [sbstjn](http://github.com/sbstjn) |
| **[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 Env Generator](https://github.com/DieProduktMacher/serverless-env-generator)** <br/> Manage environment variables with YAML and load them with dotenv. Supports variable encryption with KMS, multiple stages and custom profiles. | [DieProduktMacher](http://github.com/DieProduktMacher) |
| **[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 Gulp](https://github.com/rhythminme/serverless-gulp)** <br/> A thin task wrapper around @goserverless that allows you to automate build, test and deploy tasks using gulp | [rhythminme](http://github.com/rhythminme) |
| **[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 Kms Secrets](https://github.com/SC5/serverless-kms-secrets)** <br/> Allows to easily encrypt and decrypt secrets using KMS from the serverless CLI | [SC5](http://github.com/SC5) |
| **[Serverless Kubeless](https://github.com/serverless/serverless-kubeless)** <br/> Serverless plugin for deploying functions to Kubeless. | [serverless](http://github.com/serverless) |
| **[Serverless Local Dev Server](https://github.com/DieProduktMacher/serverless-local-dev-server)** <br/> Speeds up development of Alexa Skills, Chatbots and APIs by exposing your functions as local HTTP endpoints and mapping received events. | [DieProduktMacher](http://github.com/DieProduktMacher) |
| **[Serverless Log Forwarding](https://github.com/amplify-education/serverless-log-forwarding)** <br/> Serverless plugin for forwarding CloudWatch logs to another Lambda function. | [amplify-education](http://github.com/amplify-education) |
| **[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 Nested Stack](https://github.com/jagdish-176/serverless-nested-stack)** <br/> A plugin to Workaround for Cloudformation 200 resource limit | [jagdish-176](http://github.com/jagdish-176) |
| **[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 Aws Resolvers](https://github.com/DopplerLabs/serverless-plugin-aws-resolvers)** <br/> Resolves variables from ESS, RDS, or Kinesis for serverless services | [DopplerLabs](http://github.com/DopplerLabs) |
| **[Serverless Plugin Bespoken](https://github.com/bespoken/serverless-plugin-bespoken)** <br/> Creates a local server and a proxy so you don't have to deploy anytime you want to test your code | [bespoken](http://github.com/bespoken) |
| **[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 Browserifier](https://github.com/digitalmaas/serverless-plugin-browserifier)** <br/> Reduce the size and speed up your Node.js based lambda's using browserify. | [digitalmaas](http://github.com/digitalmaas) |
| **[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 Common Excludes](https://github.com/dougmoscrop/serverless-plugin-common-excludes)** <br/> Adds commonly excluded files to package.excludes | [dougmoscrop](http://github.com/dougmoscrop) |
| **[Serverless Plugin Custom Domain](https://github.com/dougmoscrop/serverless-plugin-custom-domain)** <br/> Reliably sets a BasePathMapping to an API Gateway Custom Domain | [dougmoscrop](http://github.com/dougmoscrop) |
| **[Serverless Plugin Deploy Environment](https://github.com/DopplerLabs/serverless-plugin-deploy-environment)** <br/> Plugin to manage deployment environment across stages | [DopplerLabs](http://github.com/DopplerLabs) |
| **[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 Elastic Beanstalk](https://github.com/rawphp/serverless-plugin-elastic-beanstalk)** <br/> A serverless plugin to deploy applications to AWS ElasticBeanstalk. | [rawphp](http://github.com/rawphp) |
| **[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) |
@ -193,12 +215,16 @@ This table is generated from https://github.com/serverless/plugins/blob/master/p
| **[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 Log Subscription](https://github.com/dougmoscrop/serverless-plugin-log-subscription)** <br/> Adds a CloudWatch LogSubscription for functions | [dougmoscrop](http://github.com/dougmoscrop) |
| **[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 Offline Kinesis Events](https://github.com/DopplerLabs/serverless-plugin-offline-kinesis-events)** <br/> Plugin that works with serverless-offline to allow offline testing of serverless functions that are triggered by Kinesis events. | [DopplerLabs](http://github.com/DopplerLabs) |
| **[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 Split Stacks](https://github.com/dougmoscrop/serverless-plugin-split-stacks)** <br/> Migrate certain resources to nested stacks | [dougmoscrop](http://github.com/dougmoscrop) |
| **[Serverless Plugin Stack Config](https://github.com/rawphp/serverless-plugin-stack-config)** <br/> A serverless plugin to manage configurations for a stack across micro-services. | [rawphp](http://github.com/rawphp) |
| **[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) |
@ -212,14 +238,20 @@ This table is generated from https://github.com/serverless/plugins/blob/master/p
| **[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 S3 Remover](https://github.com/sinofseven/serverless-s3-remover)** <br/> A serverless plugin to make s3 buckets empty before deleting cloudformation stack when ```sls remove``` | [sinofseven](http://github.com/sinofseven) |
| **[Serverless S3 Sync](https://github.com/k1LoW/serverless-s3-sync)** <br/> A plugin to sync local directories and S3 prefixes for Serverless Framework, | [k1LoW](http://github.com/k1LoW) |
| **[Serverless S3bucket Sync](https://github.com/sbstjn/serverless-s3bucket-sync)** <br/> Sync a local folder with a S3 bucket after sls deploy | [sbstjn](http://github.com/sbstjn) |
| **[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 Sentry](https://github.com/arabold/serverless-sentry-plugin)** <br/> Automatic monitoring of memory usage, execution timeouts and forwarding of Lambda errors to Sentry (https://sentry.io). | [arabold](http://github.com/arabold) |
| **[Serverless Shell](https://github.com/UnitedIncome/serverless-shell)** <br/> Drop to a runtime shell with all the environment variables set that you'd have in lambda. | [UnitedIncome](http://github.com/UnitedIncome) |
| **[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 Stack Output](https://github.com/sbstjn/serverless-stack-output)** <br/> Store output from your AWS CloudFormation Stack in JSON/YAML/TOML files, or to pass it to a JavaScript function for further processing. | [sbstjn](http://github.com/sbstjn) |
| **[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 Webpack](https://github.com/serverless-heaven/serverless-webpack)** <br/> Serverless plugin to bundle your lambdas with Webpack | [serverless-heaven](http://github.com/serverless-heaven) |
| **[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,6 +262,7 @@ This table is generated from https://github.com/serverless/examples/blob/master/
-->
| Project Name | Author |
|:-------------|:------:|
| **[Jwtauthorizr](https://github.com/serverlessbuch/jwtAuthorizr)** <br/> Custom JWT Authorizer Lambda function for Amazon API Gateway with Bearer JWT | [serverlessbuch](http://github.com/serverlessbuch) |
| **[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) |
@ -275,6 +308,14 @@ This table is generated from https://github.com/serverless/examples/blob/master/
| **[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) |
| **[Sqs Worker With Aws Lambda And Cloudwatch Alarms](https://github.com/sbstjn/sqs-worker-serverless)** <br/> Process messages stored in SQS with an [auto-scaled AWS Lambda worker](https://sbstjn.com/serverless-sqs-worker-with-aws-lambda.html) function. | [sbstjn](http://github.com/sbstjn) |
| **[Aws Lambda Power Tuning (Powered By Step Functions)](https://github.com/alexcasalboni/aws-lambda-power-tuning)** <br/> Build a [Step Functions](https://aws.amazon.com/step-functions/) state machine to optimize your AWS Lambda Function memory/power configuration. | [alexcasalboni](http://github.com/alexcasalboni) |
| **[Amazon Kinesis Streams Fan Out Via Kinesis Analytics](https://github.com/alexcasalboni/kinesis-streams-fan-out-kinesis-analytics)** <br/> Use [Amazon Kinesis Analytics](https://aws.amazon.com/kinesis/analytics/) to fan-out your Kinesis Streams and avoid read throttling. | [alexcasalboni](http://github.com/alexcasalboni) |
| **[Grants Api Serverless](https://github.com/comicrelief/grants-api-serverless)** <br/> ES6 API to consume data from an external API, ingest into Elasticsearch and return a queryable endpoint on top of Elasticsearch | [comicrelief](http://github.com/comicrelief) |
| **[Honeylambda](https://github.com/0x4D31/honeyLambda)** <br/> a simple, serverless application designed to create and monitor URL {honey}tokens, on top of AWS Lambda and Amazon API Gateway | [0x4D31](http://github.com/0x4D31) |
| **[Stack Overflow Monitor](https://github.com/picsoung/stackoverflowmonitor)** <br/> Monitor Stack Overflow questions and post them in a Slack channel | [picsoung](http://github.com/picsoung) |
| **[React & Stripe Serverless Ecommerce](https://github.com/patrick-michelberger/serverless-shop)** <br/> Serverless E-Commerce App with AWS Lambda, Stripe and React | [patrick-michelberger](http://github.com/patrick-michelberger) |
| **[Serverless + Medium Text To Speech](https://github.com/RafalWilinski/serverless-medium-text-to-speech)** <br/> Serverless-based, text-to-speech service for Medium articles | [RafalWilinski](http://github.com/RafalWilinski) |
<!-- AUTO-GENERATED-CONTENT:END This table is generated from https://github.com/serverless/examples/blob/master/community-examples.json please make additions there -->
## <a name="contributing"></a>Contributing

View File

@ -39,6 +39,10 @@ services:
image: maven:3-jdk-8
volumes:
- ./tmp/serverless-integration-test-aws-kotlin-jvm-maven:/app
aws-kotlin-nodejs-gradle:
image: pgoudreau/docker-maven-node
volumes:
- ./tmp/serverless-integration-test-aws-kotlin-nodejs-gradle:/app
aws-groovy-gradle:
image: java:8
volumes:

View File

@ -23,7 +23,7 @@ npm install -g serverless
serverless login
```
*Serverless follows the [Semantic Versioning](http://semver.org) schema. You can read more about that in our dedicated [versioning file](http://bit.ly/2eP05Iw).*
Next up, it's time to choose where you'd like your serverless service to run.
## Choose your compute provider

View File

@ -46,6 +46,7 @@ Most commonly used templates:
- aws-python
- aws-python3
- aws-kotlin-jvm-maven
- aws-kotlin-nodejs-gradle
- aws-groovy-gradle
- aws-java-maven
- aws-java-gradle

View File

@ -18,16 +18,16 @@ The `sls deploy function` command deploys an individual function without AWS Clo
serverless deploy function -f functionName
```
**Note:** Because this command is only deploying the function code, function
properties such as environment variables and events will **not** be deployed.
Those properties are deployed via CloudFormation, which does not execute with
this command.
**Note:** This command **now** deploys both function configuration and code by
default. Just as before, this puts your function in an inconsistent state that
is out of sync with your CloudFormation stack. Use this for faster development
cycles and not production deployments
## Options
- `--function` or `-f` The name of the function which should be deployed
- `--stage` or `-s` The stage in your service that you want to deploy to.
- `--region` or `-r` The region in that stage that you want to deploy to.
- `--update-config` or `-u` Pushes Lambda-level configuration changes e.g. timeout or memorySize
- `--update-config` or `-u` Pushes ONLY Lambda-level configuration changes e.g. timeout or memorySize
## Examples
@ -43,8 +43,8 @@ serverless deploy function --function helloWorld
serverless deploy function --function helloWorld --stage dev --region us-east-1
```
### Deployment with configuration change
### Deploy only configuration changes
```bash
serverless deploy function --function helloWorld --update-config
```
```

View File

@ -96,7 +96,9 @@ This example will pass the json context in the `lib/context.json` file (relative
### Limitations
Currently, `invoke local` only supports the NodeJs and Python runtimes.
Currently, `invoke local` only supports the NodeJs, Python & Java runtimes.
**Note:** In order to get correct output when using Java runtime, your Response class must implement `toString()` method.
## Resource permissions

View File

@ -35,7 +35,7 @@ serverless invoke [local] --function functionName
# Invoke Local
Invokes a function locally for testing and logs the output. You can only invoke Node.js runtime locally at the moment. Keep in mind that we mock the `context` with simple mock data.
Invokes a function locally for testing and logs the output. Keep in mind that we mock the `context` with simple mock data.
```bash
serverless invoke local --function functionName

View File

@ -56,6 +56,7 @@ Here are the available runtimes for AWS Lambda:
* aws-python
* aws-python3
* aws-kotlin-jvm-maven
* aws-kotlin-nodejs-gradle
* aws-groovy-gradle
* aws-java-gradle
* aws-java-maven

View File

@ -13,8 +13,9 @@ layout: Doc
1. Node.js `v6.5.0` or later. *(this is the runtime version supported by Azure Functions)*
2. Serverless CLI `v1.9.0` or later. You can run
`npm install -g serverless` to install it.
3. An Azure account. If you don't already have one, you can sign up for a [free trial](https://azure.microsoft.com/en-us/free/) that includes $200 of free credit.
4. **Set-up your [Provider Credentials](./credentials.md)**.
3. Azure plugin that allows you to work with Azure Functions `npm install -g serverless-azure-functions`
4. An Azure account. If you don't already have one, you can sign up for a [free trial](https://azure.microsoft.com/en-us/free/) that includes $200 of free credit.
5. **Set-up your [Provider Credentials](./credentials.md)**.
## Create a new service

View File

@ -140,6 +140,7 @@ class CLI {
this.consoleLog(chalk.yellow.underline('Commands'));
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 "--no-color" to disable CLI colors'));
this.consoleLog(chalk.dim('* Pass "--help" after any <command> for contextual help'));
this.consoleLog('');

View File

@ -67,8 +67,10 @@ class PluginManager {
}
// don't load plugins twice
const loadedPlugins = this.plugins.map(plugin => plugin.constructor.name);
if (_.includes(loadedPlugins, Plugin.name)) return;
if (this.plugins.some(plugin => plugin instanceof Plugin)) {
this.serverless.cli.log(`WARNING: duplicate plugin ${Plugin.name} was not loaded\n`);
return;
}
this.loadCommands(pluginInstance);
this.loadHooks(pluginInstance);

View File

@ -546,6 +546,28 @@ describe('PluginManager', () => {
expect(pluginManager.plugins.length).to.equal(1);
});
it('should load two plugins that happen to have the same class name', () => {
function getFirst() {
return class PluginMock {
};
}
function getSecond() {
return class PluginMock {
};
}
const first = getFirst();
const second = getSecond();
pluginManager.addPlugin(first);
pluginManager.addPlugin(second);
expect(pluginManager.plugins[0]).to.be.instanceof(first);
expect(pluginManager.plugins[1]).to.be.instanceof(second);
expect(pluginManager.plugins.length).to.equal(2);
});
it('should load the plugin commands', () => {
pluginManager.addPlugin(SynchronousPluginMock);

View File

@ -21,7 +21,7 @@ class Variables {
this.cfRefSyntax = RegExp(/^cf:/g);
this.s3RefSyntax = RegExp(/^s3:(.+?)\/(.+)$/);
this.stringRefSynax = RegExp(/('.*')|(".*")/g);
this.ssmRefSyntax = RegExp(/^ssm:([a-zA-Z0-9_.-/]+)[~]?(true|false)?/);
this.ssmRefSyntax = RegExp(/^ssm:([a-zA-Z0-9_.\-/]+)[~]?(true|false)?/);
}
loadVariableSyntax() {

View File

@ -946,21 +946,23 @@ describe('Variables', () => {
});
it('should get variable from Ssm using regular-style param', () => {
const param = 'Param-01_valid.chars';
const value = 'MockValue';
const awsResponseMock = {
Parameter: {
Value: 'MockValue',
Value: value,
},
};
const ssmStub = sinon.stub(awsProvider, 'request').resolves(awsResponseMock);
return serverless.variables.getValueFromSsm('ssm:param').then(value => {
expect(value).to.be.equal('MockValue');
return serverless.variables.getValueFromSsm(`ssm:${param}`).then(resolved => {
expect(resolved).to.be.equal(value);
expect(ssmStub.calledOnce).to.be.equal(true);
expect(ssmStub.calledWithExactly(
'SSM',
'getParameter',
{
Name: 'param',
Name: param,
WithDecryption: false,
},
serverless.variables.options.stage,
@ -970,21 +972,23 @@ describe('Variables', () => {
});
it('should get variable from Ssm using path-style param', () => {
const param = '/path/to/Param-01_valid.chars';
const value = 'MockValue';
const awsResponseMock = {
Parameter: {
Value: 'MockValue',
Value: value,
},
};
const ssmStub = sinon.stub(awsProvider, 'request').resolves(awsResponseMock);
return serverless.variables.getValueFromSsm('ssm:/some/path/to/param').then(value => {
expect(value).to.be.equal('MockValue');
return serverless.variables.getValueFromSsm(`ssm:${param}`).then(resolved => {
expect(resolved).to.be.equal(value);
expect(ssmStub.calledOnce).to.be.equal(true);
expect(ssmStub.calledWithExactly(
'SSM',
'getParameter',
{
Name: '/some/path/to/param',
Name: param,
WithDecryption: false,
},
serverless.variables.options.stage,
@ -994,21 +998,23 @@ describe('Variables', () => {
});
it('should get encrypted variable from Ssm using extended syntax', () => {
const param = '/path/to/Param-01_valid.chars';
const value = 'MockValue';
const awsResponseMock = {
Parameter: {
Value: 'MockValue',
Value: value,
},
};
const ssmStub = sinon.stub(awsProvider, 'request').resolves(awsResponseMock);
return serverless.variables.getValueFromSsm('ssm:/some/path/to/param~true').then(value => {
expect(value).to.be.equal('MockValue');
return serverless.variables.getValueFromSsm(`ssm:${param}~true`).then(resolved => {
expect(resolved).to.be.equal(value);
expect(ssmStub.calledOnce).to.be.equal(true);
expect(ssmStub.calledWithExactly(
'SSM',
'getParameter',
{
Name: '/some/path/to/param',
Name: param,
WithDecryption: true,
},
serverless.variables.options.stage,
@ -1018,21 +1024,23 @@ describe('Variables', () => {
});
it('should get unencrypted variable from Ssm using extended syntax', () => {
const param = '/path/to/Param-01_valid.chars';
const value = 'MockValue';
const awsResponseMock = {
Parameter: {
Value: 'MockValue',
Value: value,
},
};
const ssmStub = sinon.stub(awsProvider, 'request').resolves(awsResponseMock);
return serverless.variables.getValueFromSsm('ssm:/some/path/to/param~false').then(value => {
expect(value).to.be.equal('MockValue');
return serverless.variables.getValueFromSsm(`ssm:${param}~false`).then(resolved => {
expect(resolved).to.be.equal(value);
expect(ssmStub.calledOnce).to.be.equal(true);
expect(ssmStub.calledWithExactly(
'SSM',
'getParameter',
{
Name: '/some/path/to/param',
Name: param,
WithDecryption: false,
},
serverless.variables.options.stage,
@ -1042,28 +1050,29 @@ describe('Variables', () => {
});
it('should ignore bad values for extended syntax', () => {
const param = '/path/to/Param-01_valid.chars';
const value = 'MockValue';
const awsResponseMock = {
Parameter: {
Value: 'MockValue',
Value: value,
},
};
const ssmStub = sinon.stub(awsProvider, 'request').resolves(awsResponseMock);
return serverless.variables.getValueFromSsm('ssm:/some/path/to/param~badvalue')
.then(value => {
expect(value).to.be.equal('MockValue');
expect(ssmStub.calledOnce).to.be.equal(true);
expect(ssmStub.calledWithExactly(
'SSM',
'getParameter',
{
Name: '/some/path/to/param',
WithDecryption: false,
},
serverless.variables.options.stage,
serverless.variables.options.region
)).to.be.equal(true);
});
return serverless.variables.getValueFromSsm(`ssm:${param}~badvalue`).then(resolved => {
expect(resolved).to.be.equal(value);
expect(ssmStub.calledOnce).to.be.equal(true);
expect(ssmStub.calledWithExactly(
'SSM',
'getParameter',
{
Name: param,
WithDecryption: false,
},
serverless.variables.options.stage,
serverless.variables.options.region
)).to.be.equal(true);
});
});
it('should return undefined if SSM parameter does not exist', () => {

View File

@ -44,7 +44,7 @@ module.exports = {
}
return this.provider.request('S3',
'putObject',
'upload',
params,
this.options.stage,
this.options.region);
@ -73,7 +73,7 @@ module.exports = {
}
return this.provider.request('S3',
'putObject',
'upload',
params,
this.options.stage,
this.options.region);
@ -83,7 +83,7 @@ module.exports = {
let shouldUploadService = false;
this.serverless.cli.log('Uploading artifacts...');
const functionNames = this.serverless.service.getAllFunctions();
const uploadPromises = functionNames.map(name => {
return BbPromise.map(functionNames, (name) => {
const functionArtifactFileName = this.provider.naming.getFunctionArtifactName(name);
const functionObject = this.serverless.service.getFunction(name);
functionObject.package = functionObject.package || {};
@ -100,9 +100,7 @@ module.exports = {
return BbPromise.resolve();
}
return this.uploadZipFile(artifactFilePath);
});
return BbPromise.all(uploadPromises).then(() => {
}, { concurrency: 3 }).then(() => {
if (shouldUploadService) {
const artifactFileName = this.provider.naming.getServiceArtifactName();
const artifactFilePath = path.join(this.packagePath, artifactFileName);

View File

@ -70,13 +70,13 @@ describe('uploadArtifacts', () => {
describe('#uploadCloudFormationFile()', () => {
let normalizeCloudFormationTemplateStub;
let putObjectStub;
let uploadStub;
beforeEach(() => {
normalizeCloudFormationTemplateStub = sinon
.stub(normalizeFiles, 'normalizeCloudFormationTemplate')
.returns();
putObjectStub = sinon
uploadStub = sinon
.stub(awsDeploy.provider, 'request')
.resolves();
});
@ -91,10 +91,10 @@ describe('uploadArtifacts', () => {
return awsDeploy.uploadCloudFormationFile().then(() => {
expect(normalizeCloudFormationTemplateStub.calledOnce).to.equal(true);
expect(putObjectStub.calledOnce).to.equal(true);
expect(putObjectStub.calledWithExactly(
expect(uploadStub.calledOnce).to.equal(true);
expect(uploadStub.calledWithExactly(
'S3',
'putObject',
'upload',
{
Bucket: awsDeploy.bucketName,
Key: `${awsDeploy.serverless.service.package
@ -121,10 +121,10 @@ describe('uploadArtifacts', () => {
return awsDeploy.uploadCloudFormationFile().then(() => {
expect(normalizeCloudFormationTemplateStub.calledOnce).to.equal(true);
expect(putObjectStub.calledOnce).to.be.equal(true);
expect(putObjectStub.calledWithExactly(
expect(uploadStub.calledOnce).to.be.equal(true);
expect(uploadStub.calledWithExactly(
'S3',
'putObject',
'upload',
{
Bucket: awsDeploy.bucketName,
Key: `${awsDeploy.serverless.service.package
@ -147,13 +147,13 @@ describe('uploadArtifacts', () => {
describe('#uploadZipFile()', () => {
let readFileSyncStub;
let putObjectStub;
let uploadStub;
beforeEach(() => {
readFileSyncStub = sinon
.stub(fs, 'readFileSync')
.returns();
putObjectStub = sinon
uploadStub = sinon
.stub(awsDeploy.provider, 'request')
.resolves();
});
@ -175,11 +175,11 @@ describe('uploadArtifacts', () => {
serverless.utils.writeFileSync(artifactFilePath, 'artifact.zip file content');
return awsDeploy.uploadZipFile(artifactFilePath).then(() => {
expect(putObjectStub.calledOnce).to.be.equal(true);
expect(uploadStub.calledOnce).to.be.equal(true);
expect(readFileSyncStub.calledOnce).to.equal(true);
expect(putObjectStub.calledWithExactly(
expect(uploadStub.calledWithExactly(
'S3',
'putObject',
'upload',
{
Bucket: awsDeploy.bucketName,
Key: `${awsDeploy.serverless.service.package.artifactDirectoryName}/artifact.zip`,
@ -207,11 +207,11 @@ describe('uploadArtifacts', () => {
};
return awsDeploy.uploadZipFile(artifactFilePath).then(() => {
expect(putObjectStub.calledOnce).to.be.equal(true);
expect(uploadStub.calledOnce).to.be.equal(true);
expect(readFileSyncStub.calledOnce).to.equal(true);
expect(putObjectStub.calledWithExactly(
expect(uploadStub.calledWithExactly(
'S3',
'putObject',
'upload',
{
Bucket: awsDeploy.bucketName,
Key: `${awsDeploy.serverless.service.package.artifactDirectoryName}/artifact.zip`,

View File

@ -1 +1,5 @@
*.pyc
java/target
java/.project
java/.settings
java/.classpath

View File

@ -3,6 +3,7 @@
const BbPromise = require('bluebird');
const _ = require('lodash');
const os = require('os');
const fs = BbPromise.promisifyAll(require('fs'));
const path = require('path');
const validate = require('../lib/validate');
const chalk = require('chalk');
@ -137,8 +138,17 @@ class AwsInvokeLocal {
this.options.context);
}
if (runtime === 'java8') {
return this.invokeLocalJava(
'java',
handler,
this.serverless.service.package.artifact,
this.options.data,
this.options.context);
}
throw new this.serverless.classes
.Error('You can only invoke Node.js & Python functions locally.');
.Error('You can only invoke Node.js, Python & Java functions locally.');
}
invokeLocalPython(runtime, handlerPath, handlerName, event, context) {
@ -163,6 +173,68 @@ class AwsInvokeLocal {
});
}
callJavaBridge(artifactPath, className, input) {
return new BbPromise((resolve) => fs.statAsync(artifactPath).then(() => {
const java = spawn('java', [
`-DartifactPath=${artifactPath}`,
`-DclassName=${className}`,
'-jar',
path.join(__dirname, 'java', 'target', 'invoke-bridge-1.0.jar'),
]);
this.serverless.cli.log([
'In order to get human-readable output,',
' please implement "toString()" method of your "ApiGatewayResponse" object.',
].join(''));
java.stdout.on('data', (buf) => this.serverless.cli.consoleLog(buf.toString()));
java.stderr.on('data', (buf) => this.serverless.cli.consoleLog(buf.toString()));
java.stdin.write(input);
java.stdin.end();
java.on('close', () => resolve());
}).catch(() => {
throw new Error(`Artifact ${artifactPath} doesn't exists, please compile it first.`);
}));
}
invokeLocalJava(runtime, className, artifactPath, event, customContext) {
const timeout = Number(this.options.functionObj.timeout)
|| Number(this.serverless.service.provider.timeout)
|| 6;
const context = {
name: this.options.functionObj.name,
version: 'LATEST',
logGroupName: this.provider.naming.getLogGroupName(this.options.functionObj.name),
timeout,
};
const input = JSON.stringify({
event: event || {},
context: customContext || context,
});
const javaBridgePath = path.join(__dirname, 'java');
const executablePath = path.join(javaBridgePath, 'target');
return new BbPromise(resolve => fs.statAsync(executablePath)
.then(() => this.callJavaBridge(artifactPath, className, input))
.then(resolve)
.catch(() => {
const mvn = spawn('mvn', [
'package',
'-f',
path.join(javaBridgePath, 'pom.xml'),
]);
this.serverless.cli
.log('Building Java bridge, first invocation might take a bit longer.');
mvn.stderr.on('data', (buf) => this.serverless.cli.consoleLog(`mvn - ${buf.toString()}`));
mvn.stdin.end();
mvn.on('close', () => this.callJavaBridge(artifactPath, className, input).then(resolve));
}));
}
invokeLocalNodeJs(handlerPath, handlerName, event, customContext) {
let lambda;

View File

@ -3,6 +3,9 @@
const expect = require('chai').expect;
const sinon = require('sinon');
const path = require('path');
const mockRequire = require('mock-require');
const EventEmitter = require('events');
const fse = require('fs-extra');
const AwsInvokeLocal = require('./index');
const AwsProvider = require('../provider/awsProvider');
const Serverless = require('../../../Serverless');
@ -276,12 +279,15 @@ describe('AwsInvokeLocal', () => {
describe('#invokeLocal()', () => {
let invokeLocalNodeJsStub;
let invokeLocalPythonStub;
let invokeLocalJavaStub;
beforeEach(() => {
invokeLocalNodeJsStub =
sinon.stub(awsInvokeLocal, 'invokeLocalNodeJs').resolves();
invokeLocalPythonStub =
sinon.stub(awsInvokeLocal, 'invokeLocalPython').resolves();
invokeLocalJavaStub =
sinon.stub(awsInvokeLocal, 'invokeLocalJava').resolves();
awsInvokeLocal.serverless.service.service = 'new-service';
awsInvokeLocal.options = {
@ -298,6 +304,7 @@ describe('AwsInvokeLocal', () => {
afterEach(() => {
awsInvokeLocal.invokeLocalNodeJs.restore();
awsInvokeLocal.invokeLocalPython.restore();
awsInvokeLocal.invokeLocalJava.restore();
});
it('should call invokeLocalNodeJs when no runtime is set', () => awsInvokeLocal.invokeLocal()
@ -352,12 +359,26 @@ describe('AwsInvokeLocal', () => {
{},
undefined
)).to.be.equal(true);
delete awsInvokeLocal.options.functionObj.runtime;
});
});
it('throw error when using runtime other than Node.js or Python', () => {
it('should call invokeLocalJava when java8 runtime is set', () => {
awsInvokeLocal.options.functionObj.runtime = 'java8';
return awsInvokeLocal.invokeLocal()
.then(() => {
expect(invokeLocalJavaStub.calledOnce).to.be.equal(true);
expect(invokeLocalJavaStub.calledWithExactly(
'java',
'handler.hello',
undefined,
{},
undefined
)).to.be.equal(true);
});
});
it('throw error when using runtime other than Node.js or Python', () => {
awsInvokeLocal.options.functionObj.runtime = 'invalid-runtime';
expect(() => awsInvokeLocal.invokeLocal()).to.throw(Error);
delete awsInvokeLocal.options.functionObj.runtime;
});
@ -507,4 +528,183 @@ describe('AwsInvokeLocal', () => {
});
});
});
describe('#callJavaBridge()', () => {
let awsInvokeLocalMocked;
let writeChildStub;
let endChildStub;
beforeEach(() => {
writeChildStub = sinon.stub();
endChildStub = sinon.stub();
mockRequire('child_process', {
spawn: () => ({
stderr: new EventEmitter().on('data', () => {}),
stdout: new EventEmitter().on('data', () => {}),
stdin: {
write: writeChildStub,
end: endChildStub,
},
on: (key, callback) => callback(),
}),
});
// Remove Node.js internal "require cache" contents and re-require ./index.js
delete require.cache[require.resolve('./index')];
delete require.cache[require.resolve('child_process')];
const AwsInvokeLocalMocked = require('./index'); // eslint-disable-line global-require
serverless.setProvider('aws', new AwsProvider(serverless));
awsInvokeLocalMocked = new AwsInvokeLocalMocked(serverless, options);
awsInvokeLocalMocked.options = {
stage: 'dev',
function: 'first',
functionObj: {
handler: 'handler.hello',
name: 'hello',
timeout: 4,
},
data: {},
};
});
afterEach(() => {
delete require.cache[require.resolve('./index')];
delete require.cache[require.resolve('child_process')];
});
it('spawns java process with correct arguments', () =>
awsInvokeLocalMocked.callJavaBridge(
__dirname,
'com.serverless.Handler',
'{}'
).then(() => {
expect(writeChildStub.calledOnce).to.be.equal(true);
expect(endChildStub.calledOnce).to.be.equal(true);
expect(writeChildStub.calledWithExactly('{}')).to.be.equal(true);
})
);
});
describe('#invokeLocalJava()', () => {
const bridgePath = path.join(__dirname, 'java', 'target');
let callJavaBridgeStub;
beforeEach(() => {
fse.mkdirsSync(bridgePath);
callJavaBridgeStub = sinon.stub(awsInvokeLocal, 'callJavaBridge').resolves();
awsInvokeLocal.options = {
stage: 'dev',
function: 'first',
functionObj: {
handler: 'handler.hello',
name: 'hello',
timeout: 4,
},
data: {},
};
});
afterEach(() => {
awsInvokeLocal.callJavaBridge.restore();
fse.removeSync(bridgePath);
});
it('should invoke callJavaBridge when bridge is built', () =>
awsInvokeLocal.invokeLocalJava(
'java',
'com.serverless.Handler',
__dirname,
{}
).then(() => {
expect(callJavaBridgeStub.calledOnce).to.be.equal(true);
expect(callJavaBridgeStub.calledWithExactly(
__dirname,
'com.serverless.Handler',
JSON.stringify({
event: {},
context: {
name: 'hello',
version: 'LATEST',
logGroupName: '/aws/lambda/hello',
timeout: 4,
},
})
)).to.be.equal(true);
})
);
describe('when attempting to build the Java bridge', () => {
let awsInvokeLocalMocked;
let callJavaBridgeMockedStub;
beforeEach(() => {
mockRequire('child_process', {
spawn: () => ({
stderr: new EventEmitter().on('data', () => {}),
stdout: new EventEmitter().on('data', () => {}),
stdin: {
write: () => {},
end: () => {},
},
on: (key, callback) => callback(),
}),
});
// Remove Node.js internal "require cache" contents and re-require ./index.js
delete require.cache[require.resolve('./index')];
delete require.cache[require.resolve('child_process')];
const AwsInvokeLocalMocked = require('./index'); // eslint-disable-line global-require
serverless.setProvider('aws', new AwsProvider(serverless));
awsInvokeLocalMocked = new AwsInvokeLocalMocked(serverless, options);
callJavaBridgeMockedStub = sinon.stub(awsInvokeLocalMocked, 'callJavaBridge').resolves();
awsInvokeLocalMocked.options = {
stage: 'dev',
function: 'first',
functionObj: {
handler: 'handler.hello',
name: 'hello',
timeout: 4,
},
data: {},
};
});
afterEach(() => {
awsInvokeLocalMocked.callJavaBridge.restore();
delete require.cache[require.resolve('./index')];
delete require.cache[require.resolve('child_process')];
});
it('if it\'s not present yet', () =>
awsInvokeLocalMocked.invokeLocalJava(
'java',
'com.serverless.Handler',
__dirname,
{}
).then(() => {
expect(callJavaBridgeMockedStub.calledOnce).to.be.equal(true);
expect(callJavaBridgeMockedStub.calledWithExactly(
__dirname,
'com.serverless.Handler',
JSON.stringify({
event: {},
context: {
name: 'hello',
version: 'LATEST',
logGroupName: '/aws/lambda/hello',
timeout: 4,
},
})
)).to.be.equal(true);
})
);
});
});
});

View File

@ -0,0 +1,2 @@
Manifest-version: 1.0
Main-Class: com.serverless.InvokeBridge

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.serverless</groupId>
<artifactId>invoke-bridge</artifactId>
<version>1.0</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-log4j</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.serverless.InvokeBridge</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,86 @@
package com.serverless;
import com.amazonaws.services.lambda.runtime.Client;
import com.amazonaws.services.lambda.runtime.ClientContext;
import com.amazonaws.services.lambda.runtime.CognitoIdentity;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import java.util.Map;
public class Context implements com.amazonaws.services.lambda.runtime.Context {
private String name;
private String version;
private String logGroupName;
private long endTime;
Context(String name, String version, String logGroupName, int timeout) {
this.name = name;
this.version = version;
this.logGroupName = logGroupName;
this.endTime = System.currentTimeMillis() + (timeout * 1000);
}
public String getAwsRequestId() {
return "1234567890";
}
public String getLogGroupName() {
return this.logGroupName;
}
public String getLogStreamName() {
return "LogStream_" + this.name;
}
public String getFunctionName() {
return this.name;
}
public String getFunctionVersion() {
return this.version;
}
public String getInvokedFunctionArn() {
return "arn:aws:lambda:serverless:" + this.name;
}
public CognitoIdentity getIdentity() {
return new CognitoIdentity() {
public String getIdentityId() {
return "1";
}
public String getIdentityPoolId() {
return "1";
}
};
}
public ClientContext getClientContext() {
return new ClientContext() {
public Client getClient() {
return null;
}
public Map<String, String> getCustom() {
return null;
}
public Map<String, String> getEnvironment() {
return System.getenv();
}
};
}
public int getRemainingTimeInMillis() {
return Math.max(0, (int) (this.endTime - System.currentTimeMillis()));
}
public int getMemoryLimitInMB() {
return 1024;
}
public LambdaLogger getLogger() {
return System.out::println;
}
}

View File

@ -0,0 +1,88 @@
package com.serverless;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
public class InvokeBridge {
private File artifact;
private String className;
private Object instance;
private Class clazz;
private InvokeBridge() {
this.artifact = new File(new File("."), System.getProperty("artifactPath"));
this.className = System.getProperty("className");
try {
HashMap<String, Object> parsedInput = parseInput(getInput());
HashMap<String, Object> eventMap = (HashMap<String, Object>) parsedInput.get("event");
this.instance = this.getInstance();
System.out.println(this.invoke(eventMap, this.getContext(parsedInput)).toString());
} catch (Exception e) {
e.printStackTrace();
}
}
private Context getContext(HashMap<String, Object> parsedInput) {
HashMap<String, Object> contextMap = (HashMap<String, Object>) parsedInput.get("context");
String name = (String) contextMap.getOrDefault("name", "functionName");
String version = (String) contextMap.getOrDefault("version", "LATEST");
String logGroupName = (String) contextMap.getOrDefault("logGroupName", "logGroup");
int timeout = Integer.parseInt(String.valueOf(contextMap.getOrDefault("timeout", 5)));
return new Context(name, version, logGroupName, timeout);
}
private Object getInstance() throws Exception {
URL[] urls = {this.artifact.toURI().toURL()};
URLClassLoader child = new URLClassLoader(urls, this.getClass().getClassLoader());
this.clazz = Class.forName(this.className, true, child);
return this.clazz.newInstance();
}
private Object invoke(HashMap<String, Object> event, Context context) throws Exception {
Method[] methods = this.clazz.getDeclaredMethods();
return methods[1].invoke(this.instance, event, context);
}
private HashMap<String, Object> parseInput(String input) throws IOException {
TypeReference<HashMap<String,Object>> typeRef = new TypeReference<HashMap<String,Object>>() {};
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(input);
return mapper.convertValue(jsonNode, typeRef);
}
private String getInput() throws IOException {
BufferedReader streamReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
StringBuilder inputStringBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null) {
inputStringBuilder.append(inputStr);
}
return inputStringBuilder.toString();
}
public static void main(String[] args) {
new InvokeBridge();
}
}

View File

@ -17,6 +17,7 @@ const validTemplates = [
'aws-java-maven',
'aws-java-gradle',
'aws-kotlin-jvm-maven',
'aws-kotlin-nodejs-gradle',
'aws-scala-sbt',
'aws-csharp',
'aws-fsharp',

View File

@ -228,6 +228,34 @@ describe('Create', () => {
});
});
it('should generate scaffolding for "aws-kotlin-nodejs-gradle" template', () => {
process.chdir(tmpDir);
create.options.template = 'aws-kotlin-nodejs-gradle';
return create.create().then(() => {
const dirContent = walkDirSync(tmpDir)
.map(elem => elem.replace(path.join(tmpDir, path.sep), ''));
expect(dirContent).to.include('serverless.yml');
expect(dirContent).to.include('build.gradle');
expect(dirContent).to.include('gradlew');
expect(dirContent).to.include('gradlew.bat');
expect(dirContent).to.include('package.json');
expect(dirContent).to.include(path.join('gradle', 'wrapper',
'gradle-wrapper.jar'));
expect(dirContent).to.include(path.join('gradle', 'wrapper',
'gradle-wrapper.properties'));
expect(dirContent).to.include(path.join('src', 'main', 'kotlin', 'com', 'serverless',
'Handler.kt'));
expect(dirContent).to.include(path.join('src', 'main', 'kotlin', 'com', 'serverless',
'ApiGatewayResponse.kt'));
expect(dirContent).to.include(path.join('src', 'main', 'kotlin', 'com', 'serverless',
'Response.kt'));
expect(dirContent).to.include(path.join('src', 'test', 'kotlin', '.gitkeep'));
expect(dirContent).to.include(path.join('.gitignore'));
});
});
it('should generate scaffolding for "aws-java-gradle" template', () => {
process.chdir(tmpDir);
create.options.template = 'aws-java-gradle';

View File

@ -3,6 +3,7 @@ package com.serverless;
import java.util.Collections;
import java.util.Map;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import com.amazonaws.services.lambda.runtime.Context;
@ -14,6 +15,8 @@ public class Handler implements RequestHandler<Map<String, Object>, ApiGatewayRe
@Override
public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
BasicConfigurator.configure();
LOG.info("received: " + input);
Response responseBody = new Response("Go Serverless v1.x! Your function executed successfully!", input);
return ApiGatewayResponse.builder()

View File

@ -0,0 +1,31 @@
group 'serverless-kotlin-node'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.1.1'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin2js'
repositories {
mavenCentral()
}
dependencies {
compile (
"org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
)
}
compileKotlin2Js.kotlinOptions {
moduleKind = "commonjs"
outputFile = "build/index.js"
}

View File

@ -0,0 +1,15 @@
*.class
target
/bin/
/.settings/
.project
.classpath
.gradle
build/
# Serverless directories
.serverless%
# package directories
node_modules
jspm_packages

View File

@ -0,0 +1,6 @@
#Sat Sep 09 11:10:27 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip

View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save ( ) {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View File

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,5 @@
{
"dependencies": {
"kotlin": "^1.1.4"
}
}

View File

@ -0,0 +1,94 @@
# Welcome to Serverless!
#
# This file is the main config file for your service.
# It's very minimal at this point and uses default values.
# You can always add more config options for more control.
# We've included some commented out config examples here.
# Just uncomment any of them to get that config option.
#
# For full config options, check the docs:
# docs.serverless.com
#
# Happy Coding!
service: aws-kotlin-nodejs-gradle # NOTE: update this with your service name
# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
# frameworkVersion: "=X.X.X"
provider:
name: aws
runtime: nodejs6.10
# you can overwrite defaults here
# stage: dev
# region: us-east-1
# you can add statements to the Lambda function's IAM Role here
# iamRoleStatements:
# - Effect: "Allow"
# Action:
# - "s3:ListBucket"
# Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ] }
# - Effect: "Allow"
# Action:
# - "s3:PutObject"
# Resource:
# Fn::Join:
# - ""
# - - "arn:aws:s3:::"
# - "Ref" : "ServerlessDeploymentBucket"
# - "/*"
# you can define service wide environment variables here
# environment:
# variable1: value1
functions:
hello:
handler: build/index.Handler
# The following are a few example events you can configure
# NOTE: Please make sure to change your handler code to work with those events
# Check the event documentation for details
# events:
# - http:
# path: users/create
# method: get
# - s3: ${env:BUCKET}
# - schedule: rate(10 minutes)
# - sns: greeter-topic
# - stream: arn:aws:dynamodb:region:XXXXXX:table/foo/stream/1970-01-01T00:00:00.000
# - alexaSkill
# - iot:
# sql: "SELECT * FROM 'some_topic'"
# - cloudwatchEvent:
# event:
# source:
# - "aws.ec2"
# detail-type:
# - "EC2 Instance State-change Notification"
# detail:
# state:
# - pending
# - cloudwatchLog: '/aws/lambda/hello'
# - cognitoUserPool:
# pool: MyUserPool
# trigger: PreSignUp
# Define function environment variables here
# environment:
# variable2: value2
# you can add CloudFormation resource templates here
#resources:
# Resources:
# NewResource:
# Type: AWS::S3::Bucket
# Properties:
# BucketName: my-new-bucket
# Outputs:
# NewOutput:
# Description: "Description for the output"
# Value: "Some output value"

View File

@ -0,0 +1,31 @@
class ApiGatewayResponse(
val statusCode: Int = 200,
var body: String? = null,
val headers: dynamic,
val isBase64Encoded: Boolean = false
) {
companion object {
inline fun build(block: Builder.() -> Unit) = Builder().apply(block).build()
}
class Builder {
var statusCode: Int = 200
var rawBody: String? = null
var headers: dynamic = object{}
var objectBody: Response? = null
var binaryBody: ByteArray? = null
var base64Encoded: Boolean = false
fun build(): ApiGatewayResponse {
var body: String? = null
when {
rawBody != null -> body = rawBody as String
objectBody != null -> body = objectBody.toString()
binaryBody != null -> body = binaryBody.toString()
}
return ApiGatewayResponse(statusCode, body, headers, base64Encoded)
}
}
}

View File

@ -0,0 +1,14 @@
@JsName("Handler")
public fun Handler(input: dynamic = {}, context: Any, callback: (Any?, ApiGatewayResponse) -> ApiGatewayResponse): Any {
println("Received: " + js("JSON.stringify(input)"));
val responseBody: Response = Response("Go Serverless v1.x! Your Kotlin function executed successfully!", input);
val responseHeaders: dynamic = object{}
responseHeaders["X-Powered-By"] = "AWS Lambda & serverless"
return callback(null, ApiGatewayResponse.build {
statusCode = 201
objectBody = responseBody
headers = responseHeaders
})
}

View File

@ -0,0 +1,12 @@
class Response(message: String, input: dynamic) {
val message: String = message
get
val input: dynamic = input
get
override fun toString(): String {
val stringified = js("JSON.stringify(this.input)")
return "{\"$message\": ${stringified} }";
}
}

View File

@ -24,4 +24,3 @@ functions:
- http:
method: get
path: second
integration: lambda

View File

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

View File

@ -7,10 +7,10 @@
"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"
"serverless-webpack": "^3.0.0",
"ts-loader": "^2.3.7",
"typescript": "^2.5.2",
"webpack": "^3.6.0"
},
"author": "The serverless webpack authors (https://github.com/elastic-coders/serverless-webpack)",
"license": "MIT"

View File

@ -10,13 +10,9 @@ provider:
runtime: nodejs6.10
functions:
# Example with LAMBDA-PROXY integration
# Invoking locally:
# sls webpack invoke -f hello
hello:
handler: handler.hello
events:
- http:
method: get
path: hello
integration: lambda

View File

@ -1,9 +1,17 @@
const path = require('path');
// eslint-disable-next-line import/no-unresolved
const slsw = require('serverless-webpack');
module.exports = {
entry: slsw.lib.entries,
resolve: {
extensions: [
'.js',
'.jsx',
'.json',
'.ts',
'.tsx'
]
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),

View File

@ -0,0 +1,11 @@
'use strict';
/* eslint-disable no-console */
const chalk = require('chalk');
const log = function (message) {
console.log(`Serverless: ${chalk.yellow(message)}`);
};
module.exports = log;

View File

@ -5,6 +5,8 @@ const BbPromise = require('bluebird');
const fs = BbPromise.promisifyAll(require('fs'));
const _ = require('lodash');
const os = require('os');
const chalk = require('chalk');
const log = require('./log/serverlessLog');
const findKeyChain = (astContent) => {
let content = astContent;
@ -24,6 +26,16 @@ const parseAST = (ymlAstContent, astObject) => {
let newAstObject = astObject || {};
if (ymlAstContent.mappings && _.isArray(ymlAstContent.mappings)) {
_.forEach(ymlAstContent.mappings, (v) => {
if (!v.value) {
const errorMessage = [
'Serverless: ',
`${chalk.red('Your serverless.yml has an invalid value with key:')} `,
`${chalk.red(`"${v.key.value}"`)}`,
].join('');
log(errorMessage);
return;
}
if (v.key.kind === 0 && v.value.kind === 0) {
newAstObject[findKeyChain(v)] = v.value;
} else if (v.key.kind === 0 && v.value.kind === 2) {

View File

@ -20,7 +20,7 @@ describe('#yamlAstParser', () => {
it('should add a top level object and item into the yaml file', () => {
const yamlFilePath = path.join(tmpDirPath, 'test.yaml');
writeFileSync(yamlFilePath, 'serveice: test-service');
writeFileSync(yamlFilePath, 'service: test-service');
return expect(yamlAstParser.addNewArrayItem(yamlFilePath, 'toplevel', 'foo'))
.to.be.fulfilled.then(() => {
const yaml = readFileSync(yamlFilePath, 'utf8');
@ -44,7 +44,7 @@ describe('#yamlAstParser', () => {
it('should add a multiple level object and item into the yaml file', () => {
const yamlFilePath = path.join(tmpDirPath, 'test.yaml');
writeFileSync(yamlFilePath, 'serveice: test-service');
writeFileSync(yamlFilePath, 'service: test-service');
return expect(yamlAstParser.addNewArrayItem(yamlFilePath, 'toplevel.second.third', 'foo'))
.to.be.fulfilled.then(() => {
const yaml = readFileSync(yamlFilePath, 'utf8');
@ -90,6 +90,18 @@ describe('#yamlAstParser', () => {
expect(yaml.toplevel).to.be.deep.equal(['foo']);
});
});
it('should survive with invalid yaml', () => {
const yamlFilePath = path.join(tmpDirPath, 'test.yaml');
writeFileSync(yamlFilePath, 'service:');
return expect(yamlAstParser.addNewArrayItem(yamlFilePath, 'toplevel', 'foo'))
.to.be.fulfilled.then(() => {
const yaml = readFileSync(yamlFilePath, 'utf8');
expect(yaml).to.have.property('toplevel');
expect(yaml.toplevel).to.be.deep.equal(['foo']);
});
});
});
describe('#removeExistingArrayItem()', () => {

View File

@ -18,6 +18,7 @@ integration-test aws-nodejs
integration-test aws-python
integration-test aws-python3
integration-test aws-kotlin-jvm-maven
integration-test aws-kotlin-nodejs-gradle
integration-test aws-nodejs-typescript
integration-test aws-nodejs-ecma-script
integration-test google-nodejs