├── .gitignore ├── README.md ├── architecture.png ├── deploy.sh ├── lambda ├── getPet │ └── function.py └── postPet │ └── function.py ├── remove.sh ├── swagger.yaml └── template.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # OS files 2 | *.DS_Store 3 | 4 | # Generated Files 5 | package.yaml 6 | 7 | # Misc Files 8 | .vscode/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS SAM, Swagger, API Gateway, Lambda Starter 2 | Light-weight sample to show how to use the AWS Serverless Application Model (AWS SAM) to integrate API Gateway to a separate Swagger or OpenAPI file. The demo triggers a lambda function through API gateway, and then returns the parameters passed to it to show that you can acces these parameters inside the lambda function. 3 | 4 | ![alt text](./architecture.png?raw=true "Architecture") 5 | 6 | ## Pre-requisites 7 | 1. Create an AWS Account [Link](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/) 8 | - Take note of your AWS Access Key ID, AWS Secret Access Key and 12-digit account ID 9 | 2. Install AWS CLI Commands [Link](https://docs.aws.amazon.com/cli/latest/userguide/installing.html) 10 | - If you don't know which default region name to indicate, just set it to **us-east-1** 11 | 3. Configure your local PC [Link](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) 12 | 4. Install AWS SAM Commands [Link](https://docs.aws.amazon.com/lambda/latest/dg/sam-cli-requirements.html) 13 | 14 | ## Deployment 15 | 1. Clone or download this repository. 16 | 2. Replace AWS_REGION and ACCOUNT_ID in the swagger.yaml file. 17 | ``` 18 | ... arn:aws:lambda:AWS_REGION:ACCOUNT_ID:function:PostPetFunction/invocations 19 | ... arn:aws:lambda:AWS_REGION:ACCOUNT_ID:function:GetPetFunction/invocations 20 | ``` 21 | 3. Replace UNIQUE_NAME deploy.sh and remove.sh files with some unique name. 22 | ``` 23 | BUCKET="pet-store-api-deployment-workspace-UNIQUE_NAME" 24 | ``` 25 | Important: Bucket names must be unique for all AWS users. 26 | 4. Run the following commands on your terminal: 27 | ``` 28 | $ cd aws-sam-swagger-apigateway-lambda-starter 29 | $ sh ./deploy.sh 30 | ``` 31 | Expected output: 32 | ``` 33 | > ... 34 | > Successfully created/updated stack - pet-store-stack 35 | ``` 36 | 37 | #### Removal 38 | 1. Perform the following commands: 39 | ``` 40 | $ cd aws-sam-swagger-apigateway-lambda-starter 41 | $ sh remove.sh 42 | ``` 43 | Expected output: 44 | ``` 45 | > ... 46 | > remove_bucket: pet-store-api-deployment-workspace-UNIQUE_NAME 47 | ``` 48 | -------------------------------------------------------------------------------- /architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mecsantos/aws-sam-swagger-apigateway-lambda-starter/f817fa84ea1cd919e11c3815bcafd99e98b90ee7/architecture.png -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # IMPORTANT: Bucket names must be unique for all AWS users. 4 | BUCKET="pet-store-api-deployment-workspace-" 5 | 6 | # Creates your deployment bucket if it doesn't exist yet. 7 | aws s3 mb s3://$BUCKET 8 | 9 | # Uploads files to S3 bucket and creates CloudFormation template 10 | sam package \ 11 | --template-file template.yaml \ 12 | --s3-bucket $BUCKET \ 13 | --output-template-file package.yaml 14 | 15 | # Deploys your stack 16 | sam deploy \ 17 | --template-file package.yaml \ 18 | --stack-name pet-store-stack \ 19 | --capabilities CAPABILITY_IAM 20 | -------------------------------------------------------------------------------- /lambda/getPet/function.py: -------------------------------------------------------------------------------- 1 | def handler(event, context): 2 | return event -------------------------------------------------------------------------------- /lambda/postPet/function.py: -------------------------------------------------------------------------------- 1 | def handler(event, context): 2 | return event -------------------------------------------------------------------------------- /remove.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # IMPORTANT: Bucket names must be unique for all AWS users. 4 | BUCKET="pet-store-api-deployment-workspace-UNIQUE_NAME" 5 | 6 | # Delete CloudFormation Stack 7 | aws cloudformation delete-stack \ 8 | --stack-name pet-store-stack 9 | 10 | # Delete non-empty bucket 11 | aws s3 rb s3://$BUCKET --force 12 | -------------------------------------------------------------------------------- /swagger.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | description: "This is a sample Petstore rest API to demonstrate integration between Swagger (a.k.a. OpenAPI) and AWS API Gateway." 4 | version: "1.0.0" 5 | title: "Pet Store Service" 6 | host: "petstore.com" 7 | basePath: "/v1" 8 | schemes: 9 | - "https" 10 | paths: 11 | /pet: 12 | post: 13 | tags: 14 | - "pet" 15 | summary: "Add a new pet to the store" 16 | description: "" 17 | operationId: "addPet" 18 | consumes: 19 | - "application/json" 20 | produces: 21 | - "application/json" 22 | parameters: 23 | - in: "body" 24 | name: "body" 25 | description: "Pet object that needs to be added to the store" 26 | required: true 27 | schema: 28 | $ref: "#/definitions/Pet" 29 | responses: 30 | 200: 31 | description: "Success" 32 | 400: 33 | description: "Bad Request" 34 | 401: 35 | description: "Unauthorized" 36 | 500: 37 | description: "Internal Server Error" 38 | # For AWS Integration 39 | x-amazon-apigateway-request-validators: 40 | basic: 41 | validateRequestParameters: true 42 | x-amazon-apigateway-integration: 43 | type: "aws" 44 | httpMethod: "POST" 45 | # Replace AWS_REGION and ACCOUNT_ID in uri 46 | uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:AWS_REGION:ACCOUNT_ID:function:PostPetFunction/invocations" 47 | responses: 48 | default: 49 | statusCode: 200 50 | requestTemplates: 51 | application/json: "{\r\n \"method\": \"$context.httpMethod\",\r\n \"body\" : \"$input.body\",\r\n \"headers\": {\r\n #foreach($param in $input.params().header.keySet())\r\n \"$param\": \"$util.escapeJavaScript($input.params().header.get($param))\" #if($foreach.hasNext),#end\r\n\r\n #end\r\n },\r\n \"queryParams\": {\r\n #foreach($param in $input.params().querystring.keySet())\r\n \"$param\": \"$util.escapeJavaScript($input.params().querystring.get($param))\" #if($foreach.hasNext),#end\r\n\r\n #end\r\n },\r\n \"pathParams\": {\r\n #foreach($param in $input.params().path.keySet())\r\n \"$param\": \"$util.escapeJavaScript($input.params().path.get($param))\" #if($foreach.hasNext),#end\r\n\r\n #end\r\n } \r\n}" 52 | /pet/{petId}: 53 | get: 54 | tags: 55 | - "pet" 56 | summary: "Find pet by ID" 57 | description: "Returns a single pet" 58 | operationId: "getPetById" 59 | produces: 60 | - "application/json" 61 | parameters: 62 | - name: "petId" 63 | in: "path" 64 | description: "ID of pet to return" 65 | required: true 66 | type: "integer" 67 | format: "int64" 68 | responses: 69 | 200: 70 | description: "Success" 71 | schema: 72 | $ref: "#/definitions/Pet" 73 | 400: 74 | description: "Bad Request" 75 | 401: 76 | description: "Unauthorized" 77 | 404: 78 | description: "Not Found" 79 | 500: 80 | description: "Internal Server Error" 81 | # For AWS Integration 82 | x-amazon-apigateway-request-validators: 83 | basic: 84 | validateRequestParameters: true 85 | x-amazon-apigateway-integration: 86 | type: "aws" 87 | httpMethod: "POST" 88 | # Replace AWS_REGION and ACCOUNT_ID in uri 89 | uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:AWS_REGION:ACCOUNT_ID:function:GetPetFunction/invocations" 90 | responses: 91 | default: 92 | statusCode: 200 93 | requestTemplates: 94 | application/json: "{\r\n \"method\": \"$context.httpMethod\",\r\n \"body\" : \"$input.body\",\r\n \"headers\": {\r\n #foreach($param in $input.params().header.keySet())\r\n \"$param\": \"$util.escapeJavaScript($input.params().header.get($param))\" #if($foreach.hasNext),#end\r\n\r\n #end\r\n },\r\n \"queryParams\": {\r\n #foreach($param in $input.params().querystring.keySet())\r\n \"$param\": \"$util.escapeJavaScript($input.params().querystring.get($param))\" #if($foreach.hasNext),#end\r\n\r\n #end\r\n },\r\n \"pathParams\": {\r\n #foreach($param in $input.params().path.keySet())\r\n \"$param\": \"$util.escapeJavaScript($input.params().path.get($param))\" #if($foreach.hasNext),#end\r\n\r\n #end\r\n } \r\n}" 95 | definitions: 96 | Pet: 97 | type: "object" 98 | properties: 99 | id: 100 | type: "integer" 101 | format: "int64" 102 | name: 103 | type: "string" 104 | type: 105 | type: "string" 106 | sub-type: 107 | type: "string" 108 | photoUrl: 109 | type: "string" 110 | status: 111 | type: "string" 112 | description: "Pet status in the store" 113 | enum: 114 | - "available" 115 | - "pending" 116 | - "sold" -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion : "2010-09-09" 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: Pet Store Rest API Service 4 | 5 | Resources: 6 | PetStoreApiGateway: 7 | Type: AWS::Serverless::Api 8 | Properties: 9 | StageName: Prod 10 | DefinitionUri: ./swagger.yaml 11 | PostPetFunction: 12 | Type: AWS::Serverless::Function 13 | Properties: 14 | FunctionName: PostPetFunction 15 | Runtime: python3.6 16 | Handler: function.handler 17 | CodeUri: ./lambda/postPet/ 18 | Events: 19 | PostPetApi: 20 | Type: Api 21 | Properties: 22 | RestApiId: !Ref "PetStoreApiGateway" 23 | Path: /pet 24 | Method: POST 25 | Policies: 26 | - AWSLambdaBasicExecutionRole 27 | GetPetFunction: 28 | Type: AWS::Serverless::Function 29 | Properties: 30 | FunctionName: GetPetFunction 31 | Runtime: python3.6 32 | Handler: function.handler 33 | CodeUri: ./lambda/getPet/ 34 | Events: 35 | GetPetApi: 36 | Type: Api 37 | Properties: 38 | RestApiId: !Ref "PetStoreApiGateway" 39 | Path: /pet/{petId} 40 | Method: GET 41 | Policies: 42 | - AWSLambdaBasicExecutionRole --------------------------------------------------------------------------------