mirror of
https://github.com/serverless/serverless.git
synced 2026-01-25 15:07:39 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
cc00ce5050
2
.gitignore
vendored
2
.gitignore
vendored
@ -55,4 +55,4 @@ jest
|
||||
|
||||
# DotNet
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]bj/
|
||||
|
||||
@ -56,7 +56,7 @@ services:
|
||||
volumes:
|
||||
- ./tmp/serverless-integration-test-aws-scala-sbt:/app
|
||||
aws-csharp:
|
||||
image: microsoft/dotnet:1.0.4-sdk
|
||||
image: microsoft/dotnet:2.0-sdk
|
||||
volumes:
|
||||
- ./tmp/serverless-integration-test-aws-csharp:/app
|
||||
aws-fsharp:
|
||||
@ -99,7 +99,7 @@ services:
|
||||
- ./tmp/serverless-integration-test-spotinst-ruby:/app
|
||||
spotinst-java8:
|
||||
image: maven:3-jdk-8
|
||||
volumes:
|
||||
volumes:
|
||||
- ./tmp/serverless-integration-test-spotinst-java8:/app
|
||||
webtasks-nodejs:
|
||||
image: node:6.10.3
|
||||
|
||||
@ -12,6 +12,32 @@ layout: Doc
|
||||
|
||||
# API Gateway
|
||||
|
||||
- [Lambda Proxy Integration](#lambda-proxy-integration)
|
||||
- [Simple HTTP Endpoint](#simple-http-endpoint)
|
||||
- [Example "LAMBDA-PROXY" event (default)](#example-lambda-proxy-event-default)
|
||||
- [HTTP Endpoint with Extended Options](#http-endpoint-with-extended-options)
|
||||
- [Enabling CORS](#enabling-cors)
|
||||
- [HTTP Endpoints with `AWS_IAM` Authorizers](#http-endpoints-with-awsiam-authorizers)
|
||||
- [HTTP Endpoints with Custom Authorizers](#http-endpoints-with-custom-authorizers)
|
||||
- [Catching Exceptions In Your Lambda Function](#catching-exceptions-in-your-lambda-function)
|
||||
- [Setting API keys for your Rest API](#setting-api-keys-for-your-rest-api)
|
||||
- [Request Parameters](#request-parameters)
|
||||
- [Lambda Integration](#lambda-integration)
|
||||
- [Example "LAMBDA" event (before customization)](#example-lambda-event-before-customization)
|
||||
- [Request templates](#request-templates)
|
||||
- [Default Request Templates](#default-request-templates)
|
||||
- [Custom Request Templates](#custom-request-templates)
|
||||
- [Pass Through Behavior](#pass-through-behavior)
|
||||
- [Responses](#responses)
|
||||
- [Custom Response Headers](#custom-response-headers)
|
||||
- [Custom Response Templates](#custom-response-templates)
|
||||
- [Status codes](#status-codes)
|
||||
- [Available Status Codes](#available-status-codes)
|
||||
- [Using Status Codes](#using-status-codes)
|
||||
- [Custom Status Codes](#custom-status-codes)
|
||||
- [Setting an HTTP Proxy on API Gateway](#setting-an-http-proxy-on-api-gateway)
|
||||
- [Share API Gateway and API Resources](#share-api-gateway-and-api-resources)
|
||||
|
||||
_Are you looking for tutorials on using API Gateway? Check out the following resources:_
|
||||
|
||||
> - [Add a custom domain for your API Gateway](https://serverless.com/blog/serverless-api-gateway-domain/)
|
||||
@ -634,33 +660,7 @@ See the [api gateway documentation](https://docs.aws.amazon.com/apigateway/lates
|
||||
**Notes:**
|
||||
|
||||
- A missing/empty request Content-Type is considered to be the API Gateway default (`application/json`)
|
||||
- [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/events/apigateway)
|
||||
- [API Gateway](#api-gateway)
|
||||
- [Lambda Proxy Integration](#lambda-proxy-integration)
|
||||
- [Simple HTTP Endpoint](#simple-http-endpoint)
|
||||
- [Example "LAMBDA-PROXY" event (default)](#example-lambda-proxy-event-default)
|
||||
- [HTTP Endpoint with Extended Options](#http-endpoint-with-extended-options)
|
||||
- [Enabling CORS](#enabling-cors)
|
||||
- [HTTP Endpoints with `AWS_IAM` Authorizers](#http-endpoints-with-awsiam-authorizers)
|
||||
- [HTTP Endpoints with Custom Authorizers](#http-endpoints-with-custom-authorizers)
|
||||
- [Catching Exceptions In Your Lambda Function](#catching-exceptions-in-your-lambda-function)
|
||||
- [Setting API keys for your Rest API](#setting-api-keys-for-your-rest-api)
|
||||
- [Request Parameters](#request-parameters)
|
||||
- [Lambda Integration](#lambda-integration)
|
||||
- [Example "LAMBDA" event (before customization)](#example-lambda-event-before-customization)
|
||||
- [Request templates](#request-templates)
|
||||
- [Default Request Templates](#default-request-templates)
|
||||
- [Custom Request Templates](#custom-request-templates)
|
||||
- [Pass Through Behavior](#pass-through-behavior)
|
||||
- [Responses](#responses)
|
||||
- [Custom Response Headers](#custom-response-headers)
|
||||
- [Custom Response Templates](#custom-response-templates)
|
||||
- [Status codes](#status-codes)
|
||||
- [Available Status Codes](#available-status-codes)
|
||||
- [Using Status Codes](#using-status-codes)
|
||||
- [Custom Status Codes](#custom-status-codes)
|
||||
- [Setting an HTTP Proxy on API Gateway](#setting-an-http-proxy-on-api-gateway)
|
||||
- [Share API Gateway and API Resources](#share-api-gateway-and-api-resources)
|
||||
- API Gateway docs refer to "WHEN_NO_TEMPLATE" (singular), but this will fail during creation as the actual value should be "WHEN_NO_TEMPLATES" (plural)
|
||||
|
||||
### Responses
|
||||
|
||||
@ -862,7 +862,7 @@ As your application grows, you will likely need to break it out into multiple, s
|
||||
|
||||
```yml
|
||||
service: service-name
|
||||
provider:
|
||||
provider:
|
||||
name: aws
|
||||
apiGateway:
|
||||
restApiId: xxxxxxxxxx # REST API resource ID. Default is generated by the framework
|
||||
@ -873,13 +873,14 @@ functions:
|
||||
|
||||
```
|
||||
|
||||
|
||||
If your application has many nested paths, you might also want to break them out into smaller services.
|
||||
|
||||
```yml
|
||||
service: service-a
|
||||
provider:
|
||||
provider:
|
||||
apiGateway:
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiRootResourceId: xxxxxxxxxx
|
||||
|
||||
functions:
|
||||
@ -893,10 +894,10 @@ functions:
|
||||
|
||||
```yml
|
||||
service: service-b
|
||||
provider:
|
||||
provider:
|
||||
apiGateway:
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiRootResourceId: xxxxxxxxxx
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiRootResourceId: xxxxxxxxxx
|
||||
|
||||
functions:
|
||||
create:
|
||||
@ -911,13 +912,13 @@ The above example services both reference the same parent path `/posts`. However
|
||||
|
||||
```yml
|
||||
service: service-a
|
||||
provider:
|
||||
provider:
|
||||
apiGateway:
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiRootResourceId: xxxxxxxxxx
|
||||
restApiResources:
|
||||
/posts: xxxxxxxxxx
|
||||
|
||||
|
||||
functions:
|
||||
...
|
||||
|
||||
@ -925,10 +926,10 @@ functions:
|
||||
|
||||
```yml
|
||||
service: service-b
|
||||
provider:
|
||||
provider:
|
||||
apiGateway:
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiRootResourceId: xxxxxxxxxx
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiRootResourceId: xxxxxxxxxx
|
||||
restApiResources:
|
||||
/posts: xxxxxxxxxx
|
||||
|
||||
@ -942,14 +943,14 @@ You can define more than one path resource, but by default, Serverless will gene
|
||||
|
||||
```yml
|
||||
service: service-a
|
||||
provider:
|
||||
provider:
|
||||
apiGateway:
|
||||
restApiId: xxxxxxxxxx
|
||||
restApiId: xxxxxxxxxx
|
||||
# restApiRootResourceId: xxxxxxxxxx # Optional
|
||||
restApiResources:
|
||||
/posts: xxxxxxxxxx
|
||||
/categories: xxxxxxxxx
|
||||
|
||||
|
||||
|
||||
functions:
|
||||
listPosts:
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
using Amazon.Lambda.Core;
|
||||
using System;
|
||||
|
||||
[assembly:LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
|
||||
|
||||
namespace AwsDotnetCsharp
|
||||
{
|
||||
public class Handler
|
||||
{
|
||||
public Response Hello(Request request)
|
||||
{
|
||||
return new Response("Go Serverless v1.0! Your function executed successfully!", request);
|
||||
}
|
||||
}
|
||||
|
||||
public class Response
|
||||
{
|
||||
public string Message {get; set;}
|
||||
public Request Request {get; set;}
|
||||
|
||||
public Response(string message, Request request){
|
||||
Message = message;
|
||||
Request = request;
|
||||
}
|
||||
}
|
||||
|
||||
public class Request
|
||||
{
|
||||
public string Key1 {get; set;}
|
||||
public string Key2 {get; set;}
|
||||
public string Key3 {get; set;}
|
||||
|
||||
public Request(string key1, string key2, string key3){
|
||||
Key1 = key1;
|
||||
Key2 = key2;
|
||||
Key3 = key3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ Using the `create` command we can specify one of the available [templates](https
|
||||
|
||||
The `--path` or shorthand `-p` is the location to be created with the template service files. Change directories into this new folder.
|
||||
|
||||
## 2. Build using .NET CLI tools and create zip package
|
||||
## 2. Build using .NET Core 2.X CLI tools and create zip package
|
||||
|
||||
```
|
||||
# Linux or Mac OS
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp1.0</TargetFramework>
|
||||
<AssemblyName>CsharpHandlers</AssemblyName>
|
||||
<PackageId>csharp</PackageId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Amazon.Lambda.Core" Version="1.0.0" />
|
||||
<PackageReference Include="Amazon.Lambda.Serialization.Json" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="1.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@ -1,85 +0,0 @@
|
||||
# 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-csharp # 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: dotnetcore1.0
|
||||
|
||||
# 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
|
||||
|
||||
# you can add packaging information here
|
||||
package:
|
||||
artifact: bin/release/netcoreapp1.0/deploy-package.zip
|
||||
# exclude:
|
||||
# - exclude-me.js
|
||||
# - exclude-me-dir/**
|
||||
|
||||
functions:
|
||||
hello:
|
||||
handler: CsharpHandlers::AwsDotnetCsharp.Handler::Hello
|
||||
|
||||
# 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
|
||||
|
||||
# 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"
|
||||
@ -5,6 +5,10 @@ description: Create a F# Hello World Lambda function
|
||||
layout: Doc
|
||||
-->
|
||||
|
||||
<!-- DOCS-SITE-LINK:START automatically generated -->
|
||||
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/examples/hello-world/fsharp/)
|
||||
<!-- DOCS-SITE-LINK:END -->
|
||||
|
||||
# Hello World F# Example
|
||||
|
||||
Make sure `serverless` is installed. [See installation guide](../../../guide/installation.md).
|
||||
|
||||
@ -30,7 +30,6 @@ You should also have [go](https://golang.org/doc/install) and [make](https://www
|
||||
It is always good practice to organize your `go` projects within [GOPATH](https://golang.org/doc/code.html#GOPATH), to maximize the benefits of go tooling.
|
||||
|
||||
## 1. Create a service
|
||||
There are two templates for `go`:
|
||||
|
||||
The Serverless Framework includes starter templates for various languages and providers. There are two templates for `go`.
|
||||
|
||||
@ -50,7 +49,7 @@ sls create --template aws-go --path myService
|
||||
sls create --template aws-go-dep --path myService
|
||||
```
|
||||
|
||||
Using the `create` command we can specify one of the available [templates](https://serverless.com/framework/docs/providers/aws/cli-reference/create#available-templates). For this example use aws-nodejs with the `--template` or shorthand `-t` flag.
|
||||
Using the `create` command we can specify one of the available [templates](https://serverless.com/framework/docs/providers/aws/cli-reference/create#available-templates). For this example use aws-go-dep with the `--template` or shorthand `-t` flag.
|
||||
|
||||
The `--path` or shorthand `-p` is the location to be created with the template service files.
|
||||
|
||||
|
||||
@ -45,7 +45,17 @@ provider:
|
||||
- "/*"
|
||||
|
||||
```
|
||||
Alongside `provider.iamRoleStatements` managed policies can also be added to this service-wide Role, define managed policies in `provider.iamManagedPolicies`. These will also be merged into the generated IAM Role so you can use `Join`, `Ref` or any other CloudFormation method or feature here too.
|
||||
```yml
|
||||
service: new-service
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
iamManagedPolicies:
|
||||
- 'some:aws:arn:xxx:*:*'
|
||||
- 'someOther:aws:arn:xxx:*:*'
|
||||
- { 'Fn::Join': [':', ['arn:aws:iam:', { Ref: 'AWSAccountId' }, 'some/path']] }
|
||||
```
|
||||
## Custom IAM Roles
|
||||
|
||||
**WARNING:** You need to take care of the overall role setup as soon as you define custom roles.
|
||||
|
||||
@ -62,6 +62,8 @@ provider:
|
||||
rateLimit: 100
|
||||
stackTags: # Optional CF stack tags
|
||||
key: value
|
||||
iamManagedPolicies: # Optional IAM Managed Policies, which allows to include the policies into IAM Role
|
||||
- arn:aws:iam:*****:policy/some-managed-policy
|
||||
iamRoleStatements: # IAM role statements so that services can be accessed in the AWS account
|
||||
- Effect: 'Allow'
|
||||
Action:
|
||||
@ -103,6 +105,8 @@ package: # Optional deployment packaging configuration
|
||||
- .git/**
|
||||
- .travis.yml
|
||||
excludeDevDependencies: false # Config if Serverless should automatically exclude dev dependencies in the deployment package. Defaults to true
|
||||
artifact: path/to/my-artifact.zip # Own package that should be used. You must provide this file.
|
||||
individually: true # Enables individual packaging for each function. If true you must provide package for each function. Defaults to false
|
||||
|
||||
|
||||
functions:
|
||||
@ -127,6 +131,15 @@ functions:
|
||||
subnetIds:
|
||||
- subnetId1
|
||||
- subnetId2
|
||||
package:
|
||||
include: # Specify the directories and files which should be included in the deployment package for this specific function.
|
||||
- src/**
|
||||
- handler.js
|
||||
exclude: # Specify the directories and files which should be excluded in the deployment package for this specific function.
|
||||
- .git/**
|
||||
- .travis.yml
|
||||
artifact: path/to/my-artifact.zip # Own package that should be use for this specific function. You must provide this file.
|
||||
individually: true # Enables individual packaging for specific function. If true you must provide package for each function. Defaults to false
|
||||
events: # The Events that trigger this Function
|
||||
- http: # This creates an API Gateway HTTP endpoint which can be used to trigger this function. Learn more in "events/apigateway"
|
||||
path: users/create # Path for this endpoint
|
||||
|
||||
@ -116,6 +116,7 @@ provider:
|
||||
Action:
|
||||
- Update:Replace
|
||||
- Update:Delete
|
||||
Resource: "*"
|
||||
Condition:
|
||||
StringEquals:
|
||||
ResourceType:
|
||||
|
||||
@ -78,7 +78,7 @@ functions: # Your "Functions"
|
||||
x-azure-settings:
|
||||
name: req
|
||||
methods:
|
||||
- POST
|
||||
- post
|
||||
route: /users/create
|
||||
usersDelete:
|
||||
events:
|
||||
@ -86,7 +86,7 @@ functions: # Your "Functions"
|
||||
x-azure-settings:
|
||||
name: req
|
||||
methods:
|
||||
- DELETE
|
||||
- delete
|
||||
route: /users/delete
|
||||
```
|
||||
|
||||
|
||||
@ -49,4 +49,4 @@ serverless logs -f hello
|
||||
hello world!
|
||||
```
|
||||
|
||||
You can install the Kubeless CLI tool following the [../guide/installation](installation guide).
|
||||
You can install the Kubeless CLI tool following the [installation guide](../guide/installation.md).
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
/* eslint-disable no-use-before-define */
|
||||
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
@ -9,6 +10,8 @@ const BbPromise = require('bluebird');
|
||||
const filesize = require('filesize');
|
||||
const normalizeFiles = require('../../lib/normalizeFiles');
|
||||
|
||||
const NUM_CONCURRENT_UPLOADS = 3;
|
||||
|
||||
module.exports = {
|
||||
uploadArtifacts() {
|
||||
return BbPromise.bind(this)
|
||||
@ -76,36 +79,36 @@ module.exports = {
|
||||
},
|
||||
|
||||
uploadFunctions() {
|
||||
let shouldUploadService = false;
|
||||
this.serverless.cli.log('Uploading artifacts...');
|
||||
|
||||
const functionNames = this.serverless.service.getAllFunctions();
|
||||
return BbPromise.map(functionNames, (name) => {
|
||||
const functionArtifactFileName = this.provider.naming.getFunctionArtifactName(name);
|
||||
const functionObject = this.serverless.service.getFunction(name);
|
||||
functionObject.package = functionObject.package || {};
|
||||
let artifactFilePath = functionObject.package.artifact ||
|
||||
this.serverless.service.package.artifact;
|
||||
if (!artifactFilePath ||
|
||||
(this.serverless.service.artifact && !functionObject.package.artifact)) {
|
||||
if (this.serverless.service.package.individually || functionObject.package.individually) {
|
||||
const artifactFileName = functionArtifactFileName;
|
||||
artifactFilePath = path.join(this.packagePath, artifactFileName);
|
||||
return this.uploadZipFile(artifactFilePath);
|
||||
const artifactFilePaths = _.uniq(
|
||||
_.map(functionNames, (name) => {
|
||||
const functionArtifactFileName = this.provider.naming.getFunctionArtifactName(name);
|
||||
const functionObject = this.serverless.service.getFunction(name);
|
||||
functionObject.package = functionObject.package || {};
|
||||
const artifactFilePath = functionObject.package.artifact ||
|
||||
this.serverless.service.package.artifact;
|
||||
|
||||
if (!artifactFilePath ||
|
||||
(this.serverless.service.artifact && !functionObject.package.artifact)) {
|
||||
if (this.serverless.service.package.individually || functionObject.package.individually) {
|
||||
const artifactFileName = functionArtifactFileName;
|
||||
return path.join(this.packagePath, artifactFileName);
|
||||
}
|
||||
return this.provider.naming.getServiceArtifactName();
|
||||
}
|
||||
shouldUploadService = true;
|
||||
return BbPromise.resolve();
|
||||
}
|
||||
|
||||
return artifactFilePath;
|
||||
})
|
||||
);
|
||||
|
||||
return BbPromise.map(artifactFilePaths, (artifactFilePath) => {
|
||||
const stats = fs.statSync(artifactFilePath);
|
||||
this.serverless.cli.log(`Uploading service .zip file to S3 (${filesize(stats.size)})...`);
|
||||
return this.uploadZipFile(artifactFilePath);
|
||||
}, { concurrency: 3 }).then(() => {
|
||||
if (shouldUploadService) {
|
||||
const artifactFileName = this.provider.naming.getServiceArtifactName();
|
||||
const artifactFilePath = path.join(this.packagePath, artifactFileName);
|
||||
const stats = fs.statSync(artifactFilePath);
|
||||
this.serverless.cli.log(`Uploading service .zip file to S3 (${filesize(stats.size)})...`);
|
||||
return this.uploadZipFile(artifactFilePath);
|
||||
}
|
||||
return BbPromise.resolve();
|
||||
});
|
||||
}, { concurrency: NUM_CONCURRENT_UPLOADS }
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -225,19 +225,45 @@ describe('uploadArtifacts', () => {
|
||||
});
|
||||
|
||||
describe('#uploadFunctions()', () => {
|
||||
let uploadZipFileStub;
|
||||
|
||||
beforeEach(() => {
|
||||
sinon.stub(fs, 'statSync').returns({ size: 1024 });
|
||||
uploadZipFileStub = sinon.stub(awsDeploy, 'uploadZipFile').resolves();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fs.statSync.restore();
|
||||
uploadZipFileStub.restore();
|
||||
});
|
||||
|
||||
it('should upload the service artifact file to the S3 bucket', () => {
|
||||
awsDeploy.serverless.config.servicePath = 'some/path';
|
||||
awsDeploy.serverless.service.service = 'new-service';
|
||||
|
||||
sinon.stub(fs, 'statSync').returns({ size: 0 });
|
||||
return awsDeploy.uploadFunctions().then(() => {
|
||||
expect(uploadZipFileStub.calledOnce).to.be.equal(true);
|
||||
expect(uploadZipFileStub.args[0][0]).to.be.equal('new-service.zip');
|
||||
});
|
||||
});
|
||||
|
||||
const uploadZipFileStub = sinon
|
||||
.stub(awsDeploy, 'uploadZipFile').resolves();
|
||||
it('should upload a single .zip file to the S3 bucket when not packaging individually', () => {
|
||||
awsDeploy.serverless.service.functions = {
|
||||
first: {
|
||||
package: {
|
||||
artifact: 'artifact.zip',
|
||||
},
|
||||
},
|
||||
second: {
|
||||
package: {
|
||||
artifact: 'artifact.zip',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return awsDeploy.uploadFunctions().then(() => {
|
||||
expect(uploadZipFileStub.calledOnce).to.be.equal(true);
|
||||
fs.statSync.restore();
|
||||
awsDeploy.uploadZipFile.restore();
|
||||
expect(uploadZipFileStub.args[0][0]).to.be.equal('artifact.zip');
|
||||
});
|
||||
});
|
||||
|
||||
@ -256,16 +282,12 @@ describe('uploadArtifacts', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const uploadZipFileStub = sinon
|
||||
.stub(awsDeploy, 'uploadZipFile').resolves();
|
||||
|
||||
return awsDeploy.uploadFunctions().then(() => {
|
||||
expect(uploadZipFileStub.calledTwice).to.be.equal(true);
|
||||
expect(uploadZipFileStub.args[0][0])
|
||||
.to.be.equal(awsDeploy.serverless.service.functions.first.package.artifact);
|
||||
expect(uploadZipFileStub.args[1][0])
|
||||
.to.be.equal(awsDeploy.serverless.service.functions.second.package.artifact);
|
||||
uploadZipFileStub.restore();
|
||||
});
|
||||
});
|
||||
|
||||
@ -284,19 +306,12 @@ describe('uploadArtifacts', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const uploadZipFileStub = sinon
|
||||
.stub(awsDeploy, 'uploadZipFile').resolves();
|
||||
const statSyncStub = sinon.stub(fs, 'statSync').returns({ size: 1024 });
|
||||
|
||||
return awsDeploy.uploadFunctions().then(() => {
|
||||
expect(uploadZipFileStub.calledTwice).to.be.equal(true);
|
||||
expect(uploadZipFileStub.args[0][0])
|
||||
.to.be.equal(awsDeploy.serverless.service.functions.first.package.artifact);
|
||||
expect(uploadZipFileStub.args[1][0])
|
||||
.to.be.equal(awsDeploy.serverless.service.package.artifact);
|
||||
}).finally(() => {
|
||||
uploadZipFileStub.restore();
|
||||
statSyncStub.restore();
|
||||
});
|
||||
});
|
||||
|
||||
@ -304,16 +319,11 @@ describe('uploadArtifacts', () => {
|
||||
awsDeploy.serverless.config.servicePath = 'some/path';
|
||||
awsDeploy.serverless.service.service = 'new-service';
|
||||
|
||||
const statSyncStub = sinon.stub(fs, 'statSync').returns({ size: 1024 });
|
||||
const uploadZipFileStub = sinon.stub(awsDeploy, 'uploadZipFile').resolves();
|
||||
sinon.spy(awsDeploy.serverless.cli, 'log');
|
||||
|
||||
return awsDeploy.uploadFunctions().then(() => {
|
||||
const expected = 'Uploading service .zip file to S3 (1 KB)...';
|
||||
expect(awsDeploy.serverless.cli.log.calledWithExactly(expected)).to.be.equal(true);
|
||||
}).finally(() => {
|
||||
statSyncStub.restore();
|
||||
uploadZipFileStub.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -7,6 +7,7 @@ const path = require('path');
|
||||
module.exports = {
|
||||
mergeIamTemplates() {
|
||||
this.validateStatements(this.serverless.service.provider.iamRoleStatements);
|
||||
this.validateManagedPolicies(this.serverless.service.provider.iamManagedPolicies);
|
||||
return this.merge();
|
||||
},
|
||||
|
||||
@ -120,6 +121,20 @@ module.exports = {
|
||||
.Statement.concat(this.serverless.service.provider.iamRoleStatements);
|
||||
}
|
||||
|
||||
if (this.serverless.service.provider.iamManagedPolicies) {
|
||||
// add iam managed policies
|
||||
const iamManagedPolicies = this.serverless.service.provider.iamManagedPolicies;
|
||||
const resource = this.serverless.service.provider.compiledCloudFormationTemplate
|
||||
.Resources[this.provider.naming.getRoleLogicalId()].Properties;
|
||||
if (iamManagedPolicies.length > 0) {
|
||||
if (!_.has(resource, 'ManagedPolicyArns') || _.isEmpty(resource.ManagedPolicyArns)) {
|
||||
resource.ManagedPolicyArns = [];
|
||||
}
|
||||
resource.ManagedPolicyArns = resource.ManagedPolicyArns
|
||||
.concat(iamManagedPolicies);
|
||||
}
|
||||
}
|
||||
|
||||
// check if one of the functions contains vpc configuration
|
||||
const vpcConfigProvided = [];
|
||||
this.serverless.service.getAllFunctions().forEach((functionName) => {
|
||||
@ -173,4 +188,14 @@ module.exports = {
|
||||
throw new this.serverless.classes.Error(errorMessage);
|
||||
}
|
||||
},
|
||||
|
||||
validateManagedPolicies(iamManagedPolicies) {
|
||||
// Verify that iamManagedPolicies (if present) is an array
|
||||
if (!iamManagedPolicies) {
|
||||
return;
|
||||
}
|
||||
if (!_.isArray(iamManagedPolicies)) {
|
||||
throw new this.serverless.classes.Error('iamManagedPolicies should be an array of arns');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@ -155,6 +155,22 @@ describe('#mergeIamTemplates()', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should add managed policy arns', () => {
|
||||
awsPackage.serverless.service.provider.iamManagedPolicies = [
|
||||
'some:aws:arn:xxx:*:*',
|
||||
'someOther:aws:arn:xxx:*:*',
|
||||
{ 'Fn::Join': [':', ['arn:aws:iam:', { Ref: 'AWSAccountId' }, 'some/path']] },
|
||||
];
|
||||
return awsPackage.mergeIamTemplates()
|
||||
.then(() => {
|
||||
expect(awsPackage.serverless.service.provider.compiledCloudFormationTemplate
|
||||
.Resources[awsPackage.provider.naming.getRoleLogicalId()]
|
||||
.Properties
|
||||
.ManagedPolicyArns
|
||||
).to.deep.equal(awsPackage.serverless.service.provider.iamManagedPolicies);
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error if custom IAM policy statements is not an array', () => {
|
||||
awsPackage.serverless.service.provider.iamRoleStatements = {
|
||||
policy: 'some_value',
|
||||
@ -222,6 +238,12 @@ describe('#mergeIamTemplates()', () => {
|
||||
.to.throw(/statement 0 is missing.*Resource; statement 2 is missing.*Effect, Action/);
|
||||
});
|
||||
|
||||
it('should throw error if managed policies is not an array', () => {
|
||||
awsPackage.serverless.service.provider.iamManagedPolicies = 'a string';
|
||||
expect(() => awsPackage.mergeIamTemplates())
|
||||
.to.throw('iamManagedPolicies should be an array of arns');
|
||||
});
|
||||
|
||||
it('should add a CloudWatch LogGroup resource', () => {
|
||||
const normalizedName = awsPackage.provider.naming.getLogGroupLogicalId(functionName);
|
||||
return awsPackage.mergeIamTemplates().then(() => {
|
||||
|
||||
@ -34,6 +34,7 @@ const validTemplates = [
|
||||
'google-nodejs',
|
||||
'kubeless-python',
|
||||
'kubeless-nodejs',
|
||||
'openwhisk-java-maven',
|
||||
'openwhisk-nodejs',
|
||||
'openwhisk-php',
|
||||
'openwhisk-python',
|
||||
|
||||
@ -143,7 +143,6 @@ describe('Create', () => {
|
||||
expect(dirContent).to.include('aws-csharp.csproj');
|
||||
expect(dirContent).to.include('build.cmd');
|
||||
expect(dirContent).to.include('build.sh');
|
||||
expect(dirContent).to.include('global.json');
|
||||
});
|
||||
});
|
||||
|
||||
@ -264,9 +263,9 @@ describe('Create', () => {
|
||||
expect(dirContent).to.include('gradlew.bat');
|
||||
expect(dirContent).to.include('package.json');
|
||||
expect(dirContent).to.include(path.join('gradle', 'wrapper',
|
||||
'gradle-wrapper.jar'));
|
||||
'gradle-wrapper.jar'));
|
||||
expect(dirContent).to.include(path.join('gradle', 'wrapper',
|
||||
'gradle-wrapper.properties'));
|
||||
'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',
|
||||
@ -291,17 +290,17 @@ describe('Create', () => {
|
||||
expect(dirContent).to.include('gradlew');
|
||||
expect(dirContent).to.include('gradlew.bat');
|
||||
expect(dirContent).to.include(path.join('gradle', 'wrapper',
|
||||
'gradle-wrapper.jar'));
|
||||
'gradle-wrapper.jar'));
|
||||
expect(dirContent).to.include(path.join('gradle', 'wrapper',
|
||||
'gradle-wrapper.properties'));
|
||||
'gradle-wrapper.properties'));
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'resources',
|
||||
'log4j.properties'));
|
||||
'log4j.properties'));
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'java',
|
||||
'com', 'serverless', 'Handler.java'));
|
||||
'com', 'serverless', 'Handler.java'));
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'java',
|
||||
'com', 'serverless', 'ApiGatewayResponse.java'));
|
||||
'com', 'serverless', 'ApiGatewayResponse.java'));
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'java',
|
||||
'com', 'serverless', 'Response.java'));
|
||||
'com', 'serverless', 'Response.java'));
|
||||
expect(dirContent).to.include(path.join('.gitignore'));
|
||||
});
|
||||
});
|
||||
@ -319,17 +318,17 @@ describe('Create', () => {
|
||||
expect(dirContent).to.include('gradlew');
|
||||
expect(dirContent).to.include('gradlew.bat');
|
||||
expect(dirContent).to.include(path.join('gradle', 'wrapper',
|
||||
'gradle-wrapper.jar'));
|
||||
'gradle-wrapper.jar'));
|
||||
expect(dirContent).to.include(path.join('gradle', 'wrapper',
|
||||
'gradle-wrapper.properties'));
|
||||
'gradle-wrapper.properties'));
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'resources',
|
||||
'log4j.properties'));
|
||||
'log4j.properties'));
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'groovy',
|
||||
'com', 'serverless', 'Handler.groovy'));
|
||||
'com', 'serverless', 'Handler.groovy'));
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'groovy',
|
||||
'com', 'serverless', 'ApiGatewayResponse.groovy'));
|
||||
'com', 'serverless', 'ApiGatewayResponse.groovy'));
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'groovy',
|
||||
'com', 'serverless', 'Response.groovy'));
|
||||
'com', 'serverless', 'Response.groovy'));
|
||||
expect(dirContent).to.include('.gitignore');
|
||||
});
|
||||
});
|
||||
@ -354,6 +353,23 @@ describe('Create', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate scaffolding for "openwhisk-java-maven" template', () => {
|
||||
process.chdir(tmpDir);
|
||||
create.options.template = 'openwhisk-java-maven';
|
||||
|
||||
return create.create().then(() => {
|
||||
const dirContent = walkDirSync(tmpDir)
|
||||
.map(elem => elem.replace(path.join(tmpDir, path.sep), ''));
|
||||
expect(dirContent).to.include('pom.xml');
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'java',
|
||||
'com', 'example', 'FunctionApp.java'));
|
||||
expect(dirContent).to.include(path.join('src', 'test', 'java',
|
||||
'com', 'example', 'FunctionAppTest.java'));
|
||||
expect(dirContent).to.include('.gitignore');
|
||||
expect(dirContent).to.include('serverless.yml');
|
||||
});
|
||||
});
|
||||
|
||||
it('should generate scaffolding for "openwhisk-nodejs" template', () => {
|
||||
process.chdir(tmpDir);
|
||||
create.options.template = 'openwhisk-nodejs';
|
||||
@ -509,7 +525,7 @@ describe('Create', () => {
|
||||
expect(dirContent).to.include('serverless.yml');
|
||||
expect(dirContent).to.include('pom.xml');
|
||||
expect(dirContent).to.include(path.join('src', 'main', 'java',
|
||||
'com', 'serverless', 'Handler.java'));
|
||||
'com', 'serverless', 'Handler.java'));
|
||||
expect(dirContent).to.include('.gitignore');
|
||||
});
|
||||
});
|
||||
@ -608,7 +624,7 @@ describe('Create', () => {
|
||||
});
|
||||
|
||||
it('should create a custom renamed service in the directory if using ' +
|
||||
'the "path" and "name" option', () => {
|
||||
'the "path" and "name" option', () => {
|
||||
process.chdir(tmpDir);
|
||||
|
||||
create.options.path = 'my-new-service';
|
||||
@ -640,7 +656,7 @@ describe('Create', () => {
|
||||
create.options.template = 'aws-nodejs';
|
||||
create.options.path = '';
|
||||
create.serverless.utils.copyDirContentsSync(path.join(create.serverless.config.serverlessPath,
|
||||
'plugins', 'create', 'templates', create.options.template), tmpDir);
|
||||
'plugins', 'create', 'templates', create.options.template), tmpDir);
|
||||
|
||||
const dirContent = fs.readdirSync(tmpDir);
|
||||
|
||||
@ -749,7 +765,7 @@ describe('Create', () => {
|
||||
|
||||
return create.create().then(() => {
|
||||
const dirContent = walkDirSync(tmpDir)
|
||||
.map(elem => elem.replace(path.join(tmpDir, path.sep), ''));
|
||||
.map(elem => elem.replace(path.join(tmpDir, path.sep), ''));
|
||||
|
||||
expect(dirContent).to.include('serverless.yml');
|
||||
expect(dirContent).to.include(path.join('hello', 'main.go'));
|
||||
|
||||
Binary file not shown.
@ -1,7 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp1.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<AssemblyName>CsharpHandlers</AssemblyName>
|
||||
<PackageId>aws-csharp</PackageId>
|
||||
</PropertyGroup>
|
||||
@ -12,7 +13,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="1.6.0" />
|
||||
<DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
dotnet restore
|
||||
dotnet lambda package --configuration release --framework netcoreapp1.0 --output-package bin/release/netcoreapp1.0/deploy-package.zip
|
||||
dotnet lambda package --configuration release --framework netcoreapp2.0 --output-package bin/release/netcoreapp2.0/deploy-package.zip
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
#install zip
|
||||
apt-get -qq update
|
||||
apt-get -qq -y install zip
|
||||
#install zip on debian OS, since microsoft/dotnet container doesn't have zip by default
|
||||
if [ -f /etc/debian_version ]
|
||||
then
|
||||
apt -qq update
|
||||
apt -qq -y install zip
|
||||
fi
|
||||
|
||||
dotnet restore
|
||||
|
||||
#create deployment package
|
||||
dotnet lambda package --configuration release --framework netcoreapp1.0 --output-package bin/release/netcoreapp1.0/deploy-package.zip
|
||||
dotnet lambda package --configuration release --framework netcoreapp2.0 --output-package bin/release/netcoreapp2.0/deploy-package.zip
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "1.0.4"
|
||||
}
|
||||
}
|
||||
@ -19,7 +19,7 @@ service: aws-csharp # NOTE: update this with your service name
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
runtime: dotnetcore1.0
|
||||
runtime: dotnetcore2.0
|
||||
|
||||
# you can overwrite defaults here
|
||||
# stage: dev
|
||||
@ -47,7 +47,7 @@ provider:
|
||||
|
||||
# you can add packaging information here
|
||||
package:
|
||||
artifact: bin/release/netcoreapp1.0/deploy-package.zip
|
||||
artifact: bin/release/netcoreapp2.0/deploy-package.zip
|
||||
# exclude:
|
||||
# - exclude-me.js
|
||||
# - exclude-me-dir/**
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
isMacOs=`uname -a | grep Darwin`
|
||||
|
||||
#install zip
|
||||
if [ -z "$isMacOs" ]
|
||||
#install zip on debian OS, since microsoft/dotnet container doesn't have zip by default
|
||||
if [ -f /etc/debian_version ]
|
||||
then
|
||||
apt-get -qq update
|
||||
apt-get -qq -y install zip
|
||||
apt -qq update
|
||||
apt -qq -y install zip
|
||||
fi
|
||||
|
||||
dotnet restore
|
||||
|
||||
#create deployment package
|
||||
dotnet lambda package --configuration release --framework netcoreapp2.0 --output-package bin/release/netcoreapp2.0/deploy-package.zip
|
||||
|
||||
8
lib/plugins/create/templates/openwhisk-java-maven/.gitignore
vendored
Normal file
8
lib/plugins/create/templates/openwhisk-java-maven/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
target
|
||||
.vscode
|
||||
.sts4-cache
|
||||
.project
|
||||
.classpath
|
||||
.settings
|
||||
*.iml
|
||||
.idea
|
||||
47
lib/plugins/create/templates/openwhisk-java-maven/pom.xml
Normal file
47
lib/plugins/create/templates/openwhisk-java-maven/pom.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>demo-function</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<url>https://openwhisk.apache.org/</url>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<gson.version>2.8.2</gson.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>demo-function</finalName>
|
||||
<plugins>
|
||||
<!-- This helps in packaging the function depeendencies as uber jar-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -0,0 +1,49 @@
|
||||
# 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: openwhisk-java-maven # NOTE: update this with your service name
|
||||
|
||||
# Please ensure the serverless-openwhisk provider plugin is installed globally.
|
||||
# $ npm install -g serverless-openwhisk
|
||||
# ...before installing project dependencies to register this provider.
|
||||
# $ npm install
|
||||
provider:
|
||||
name: openwhisk
|
||||
runtime: java
|
||||
|
||||
# you can add packaging information here
|
||||
package:
|
||||
artifact: target/demo-function.jar
|
||||
|
||||
functions:
|
||||
demo:
|
||||
handler: com.example.FunctionApp
|
||||
|
||||
# extend the framework using plugins listed here:
|
||||
# https://github.com/serverless/plugins
|
||||
plugins:
|
||||
- "serverless-openwhisk"
|
||||
|
||||
# you can define custom triggers and trigger feeds using the resources section.
|
||||
#
|
||||
#resources:
|
||||
# triggers:
|
||||
# my_trigger:
|
||||
# parameters:
|
||||
# hello: world
|
||||
# alarm_trigger:
|
||||
# parameters:
|
||||
# hello: world
|
||||
# feed: /whisk.system/alarms/alarm
|
||||
# feed_parameters:
|
||||
# cron: '*/8 * * * * *'
|
||||
@ -0,0 +1,31 @@
|
||||
package com.example;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Hello FunctionApp
|
||||
*/
|
||||
public class FunctionApp {
|
||||
public static JsonObject main(JsonObject args) {
|
||||
JsonObject response = new JsonObject();
|
||||
response.addProperty("greetings", "Hello! Welcome to OpenWhisk");
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.example;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit test for simple function.
|
||||
*/
|
||||
public class FunctionAppTest {
|
||||
@Test
|
||||
public void testFunction() {
|
||||
JsonObject args = new JsonObject();
|
||||
JsonObject response = FunctionApp.main(args);
|
||||
assertNotNull(response);
|
||||
String greetings = response.getAsJsonPrimitive("greetings").getAsString();
|
||||
assertNotNull(greetings);
|
||||
assertEquals("Hello! Welcome to OpenWhisk", greetings);
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,7 @@ function integration-test {
|
||||
$DIR/integration-test-template $@
|
||||
}
|
||||
|
||||
integration-test aws-csharp 'apt-get -qq update && apt-get -qq -y install zip && dotnet restore && dotnet lambda package --configuration release --framework netcoreapp1.0 --output-package bin/release/netcoreapp1.0/deploy-package.zip'
|
||||
integration-test aws-csharp './build.sh'
|
||||
integration-test aws-fsharp './build.sh'
|
||||
integration-test aws-go 'cd /go/src/app && make build'
|
||||
integration-test aws-go-dep 'cd /go/src/app && make build'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user