diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..d75d1c3 --- /dev/null +++ b/Gemfile @@ -0,0 +1,13 @@ +source 'http://rubygems.org' + +gem 'sinatra' +gem 'json' +gem 'rack' +gem 'rack-contrib' +gem 'aws-record' + +# These are the dependencies that are used only for unit tests. +group :test do + gem "rspec" + gem "rack-test" +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..89ddd7a --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,61 @@ +GEM + remote: http://rubygems.org/ + specs: + aws-eventstream (1.0.1) + aws-partitions (1.114.0) + aws-record (2.1.2) + aws-sdk-dynamodb (~> 1.0) + aws-sdk-core (3.38.0) + aws-eventstream (~> 1.0) + aws-partitions (~> 1.0) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-dynamodb (1.16.0) + aws-sdk-core (~> 3, >= 3.26.0) + aws-sigv4 (~> 1.0) + aws-sigv4 (1.0.3) + diff-lcs (1.3) + jmespath (1.4.0) + json (2.1.0) + mustermann (1.0.3) + rack (2.0.6) + rack-contrib (2.1.0) + rack (~> 2.0) + rack-protection (2.0.4) + rack + rack-test (1.1.0) + rack (>= 1.0, < 3) + rspec (3.8.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-core (3.8.0) + rspec-support (~> 3.8.0) + rspec-expectations (3.8.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.8.0) + rspec-mocks (3.8.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.8.0) + rspec-support (3.8.0) + sinatra (2.0.4) + mustermann (~> 1.0) + rack (~> 2.0) + rack-protection (= 2.0.4) + tilt (~> 2.0) + tilt (2.0.8) + +PLATFORMS + ruby + +DEPENDENCIES + aws-record + json + rack + rack-contrib + rack-test + rspec + sinatra + +BUNDLED WITH + 1.16.6 diff --git a/README.md b/README.md index 2bb8da5..3b9434e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,90 @@ ## Running Ruby Sinatra on AWS Lambda -Demo code for running Ruby Sinatra on AWS Lambda +This sample code helps get you started with a simple Sinatra web app deployed on AWS Lambda + +What's Here +----------- + +This sample includes: + +* README.md - this file +* Gemfile - Gem requirements for the sample application +* app/config.ru - this file contains configuration for Rack middleware +* app/server.rb - this file contains the code for the sample service +* app/views - this directory has the template files +* spec/ - this directory contains the RSpec unit tests for the sample application +* template.yml - this file contains the description of AWS resources used by AWS + CloudFormation to deploy your infrastructure + +Getting Started +--------------- + +These directions assume you want to develop on your local computer, and not +from the Amazon EC2 instance itself. If you're on the Amazon EC2 instance, the +virtual environment is already set up for you, and you can start working on the +code. + +To work on the sample code, you'll need to clone your project's repository to your +local computer. If you haven't, do that first. You can find instructions in the +AWS CodeStar user guide. + +1. Install bundle + + $ gem install bundle + +2. Install Ruby dependencies for this service + + $ bundle install + +3. Download the Gems to the local vendor directory + + $ bundle install --deployment + +4. Create the deployment package (note: if you don't have a S3 bucket, you need to create one): + + $ aws cloudformation package \ + --template-file template.yaml \ + --output-template-file serverless-output.yaml \ + --s3-bucket { your-bucket-name } + + Alternatively, if you have SAM CLI installed, you can run the following command + which will do the same + + $ sam package \ + --template-file template.yaml \ + --output-template-file serverless-output.yaml \ + --s3-bucket { your-bucket-name } + +5. Deploying your application + + $ aws cloudformation deploy --template-file serverless-output.yaml \ + --stack-name { your-stack-name } \ + --capabilities CAPABILITY_IAM + + Or use SAM CLI + + $ sam deploy \ + --template-file serverless-output.yaml \ + --stack-name { your-stack-name } \ + --capabilities CAPABILITY_IAM + + +What Do I Do Next? +------------------ + +If you have checked out a local copy of your repository you can start making changes to the sample code. + +Learn more about Serverless Application Model (SAM) and how it works here: https://github.com/awslabs/serverless-application-model/blob/master/HOWTO.md + +AWS Lambda Developer Guide: http://docs.aws.amazon.com/lambda/latest/dg/deploying-lambda-apps.html + +How Do I Add Template Resources to My Project? +------------------ + +To add AWS resources to your project, you'll need to edit the `template.yml` +file in your project's repository. You may also need to modify permissions for +your project's worker roles. After you push the template change, AWS CloudFormation provisions the resources for you. ## License -This library is licensed under the Apache 2.0 License. +This library is licensed under the Apache 2.0 License. diff --git a/app/config.ru b/app/config.ru new file mode 100644 index 0000000..79d85a5 --- /dev/null +++ b/app/config.ru @@ -0,0 +1,8 @@ +require 'rack' +require 'rack/contrib' +require_relative './server' + +set :root, File.dirname(__FILE__) +set :views, Proc.new { File.join(root, "views") } + +run Sinatra::Application diff --git a/app/server.rb b/app/server.rb new file mode 100644 index 0000000..8b3bf10 --- /dev/null +++ b/app/server.rb @@ -0,0 +1,58 @@ +require 'sinatra' +require 'aws-record' + +################################## +# For the index page +################################## +get '/' do + erb :index +end + +################################## +# Return a Hello world JSON +################################## +get '/hello-world' do + content_type :json + { :Output => 'Hello World!' }.to_json +end + +post '/hello-world' do + content_type :json + { :Output => 'Hello World!' }.to_json +end + +################################## +# Web App with a DynamodDB table +################################## + +# Class for DynamoDB table +# This could also be another file you depend on locally. +class FeedbackServerlessSinatraTable + include Aws::Record + string_attr :id, hash_key: true + string_attr :data + epoch_time_attr :ts +end + +get '/feedback' do + erb :feedback +end + +get '/api/feedback' do + content_type :json + ret = [] + items = FeedbackServerlessSinatraTable.scan() + items.each do |r| + item = { :ts => r.ts, :data => r.data } + ret.push(item) + end + ret.sort { |a, b| a[:ts] <=> b[:ts] }.to_json +end + +post '/api/feedback' do + content_type :json + body = env["rack.input"].gets + item = FeedbackServerlessSinatraTable.new(id: SecureRandom.uuid, ts: Time.now, data: body) + item.save! # raise an exception if save fails + item.to_json +end \ No newline at end of file diff --git a/app/views/feedback.erb b/app/views/feedback.erb new file mode 100644 index 0000000..64b30c6 --- /dev/null +++ b/app/views/feedback.erb @@ -0,0 +1,94 @@ + + + + + +