lam 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +16 -8
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +107 -0
- data/Guardfile +22 -0
- data/LICENSE.txt +22 -0
- data/README.md +19 -17
- data/Rakefile +4 -0
- data/bin/lam +14 -0
- data/bin/lamb +14 -0
- data/lam.gemspec +18 -20
- data/lib/lam.rb +10 -1
- data/lib/lam/base_controller.rb +54 -0
- data/lib/lam/build.rb +43 -0
- data/lib/lam/build/handler_generator.rb +34 -0
- data/lib/lam/build/lambda_deducer.rb +47 -0
- data/lib/lam/build/templates/handler.js +156 -0
- data/lib/lam/build/traveling_ruby.rb +108 -0
- data/lib/lam/cli.rb +23 -0
- data/lib/lam/cli/help.rb +19 -0
- data/lib/lam/command.rb +25 -0
- data/lib/lam/process.rb +18 -0
- data/lib/lam/process/base_processor.rb +23 -0
- data/lib/lam/process/controller_processor.rb +36 -0
- data/lib/lam/process/help.rb +11 -0
- data/lib/lam/process/processor_deducer.rb +52 -0
- data/lib/lam/util.rb +13 -0
- data/lib/lam/version.rb +1 -1
- data/notes/design.md +43 -0
- data/notes/traveling-ruby-packaging-lam.md +26 -0
- data/notes/traveling-ruby-packaging.md +103 -0
- data/notes/traveling-ruby.md +82 -0
- data/spec/fixtures/project/.gitignore +3 -0
- data/spec/fixtures/project/.ruby-version +1 -0
- data/spec/fixtures/project/Gemfile +4 -0
- data/spec/fixtures/project/Gemfile.lock +35 -0
- data/spec/fixtures/project/app/controllers/application_controller.rb +2 -0
- data/spec/fixtures/project/app/controllers/posts_controller.rb +12 -0
- data/spec/fixtures/project/bin/lam +22 -0
- data/spec/fixtures/project/handlers/controllers/posts.js +156 -0
- data/spec/lib/cli_spec.rb +20 -0
- data/spec/lib/lam/base_controller_spec.rb +18 -0
- data/spec/lib/lam/build/lambda_deducer_spec.rb +20 -0
- data/spec/lib/lam/build_spec.rb +29 -0
- data/spec/lib/lam/process/controller_processor_spec.rb +22 -0
- data/spec/lib/lam/process/infer_spec.rb +24 -0
- data/spec/lib/lam/process_spec.rb +18 -0
- data/spec/spec_helper.rb +25 -0
- metadata +191 -21
- data/bin/console +0 -14
- data/bin/setup +0 -8
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative "base_processor"
|
2
|
+
|
3
|
+
class Lam::Process
|
4
|
+
class ControllerProcessor < Lam::Process::BaseProcessor
|
5
|
+
def run
|
6
|
+
# Use the handler value (ie: posts.create) to deduce the user's business
|
7
|
+
# code to require and run.
|
8
|
+
deducer = ProcessorDeducer.new(handler)
|
9
|
+
path = deducer.controller[:path]
|
10
|
+
code = deducer.controller[:code]
|
11
|
+
|
12
|
+
begin
|
13
|
+
require path # require "app/controllers/posts_controller.rb"
|
14
|
+
# Puts the return value of user's code to stdout because this is
|
15
|
+
# what eventually gets used by API Gateway.
|
16
|
+
# Explicitly using $stdout since puts redirected to $stderr.
|
17
|
+
|
18
|
+
# result = PostsController.new(event, context).create
|
19
|
+
result = instance_eval(code, path)
|
20
|
+
|
21
|
+
# JSON.dump is pretty robust. If it cannot dump the structure into a
|
22
|
+
# json string, it just dumps it to a plain text string.
|
23
|
+
$stdout.puts JSON.dump(result) # only place where we write to stdout.
|
24
|
+
rescue Exception => e
|
25
|
+
# Customize error message slightly so nodejs shim can process the
|
26
|
+
# returned error message.
|
27
|
+
# The "RubyError: " is a marker that the javascript shim scans for.
|
28
|
+
$stderr.puts("RubyError: #{e.class}: #{e.message}") # js needs this as the first line
|
29
|
+
backtrace = e.backtrace.map {|l| " #{l}" }
|
30
|
+
$stderr.puts(backtrace)
|
31
|
+
# $stderr.puts("END OF RUBY OUTPUT")
|
32
|
+
exit 1 # instead of re-raising to control the error backtrace output
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Lam::Process::ProcessorDeducer
|
2
|
+
def initialize(handler)
|
3
|
+
@handler = handler
|
4
|
+
end
|
5
|
+
|
6
|
+
# Deduces the path and method from the handler. Example:
|
7
|
+
#
|
8
|
+
# ProcessorDeducer.new("handlers/functions/posts.create").function
|
9
|
+
# => {path: "app/functions/posts.rb", code: "create(event, context)"}
|
10
|
+
#
|
11
|
+
# Summary:
|
12
|
+
#
|
13
|
+
# Input:
|
14
|
+
# handler: handlers/functions/posts.create
|
15
|
+
# Output:
|
16
|
+
# path: app/functions/posts.rb
|
17
|
+
# code: create(event, context) # code to instance_eval
|
18
|
+
#
|
19
|
+
# Returns: {path: path, code: code}
|
20
|
+
def function
|
21
|
+
path, meth = @handler.split('.')
|
22
|
+
path = Lam.root + path.sub("handlers", "app") + ".rb"
|
23
|
+
code = "#{meth}(event, context)"
|
24
|
+
{path: path, code: code}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Deduces the path and method from the handler. Example:
|
28
|
+
#
|
29
|
+
# ProcessorDeducer.new("handlers/controllers/posts.create").controller
|
30
|
+
# => {path: "controllers/posts_controller.rb", code: "create"}
|
31
|
+
#
|
32
|
+
# Summary:
|
33
|
+
#
|
34
|
+
# Input:
|
35
|
+
# handler: handlers/controllers/posts.create
|
36
|
+
# Output:
|
37
|
+
# path: app/controllers/posts_controller.rb
|
38
|
+
# code: create # code to instance_eval
|
39
|
+
#
|
40
|
+
# Returns: {path: path, code: code}
|
41
|
+
def controller
|
42
|
+
handler_path, meth = @handler.split('.')
|
43
|
+
|
44
|
+
path = Lam.root + handler_path.sub("handlers", "app") + "_controller.rb"
|
45
|
+
|
46
|
+
controller_name = handler_path.sub(%r{.*handlers/controllers/}, "") + "_controller" # posts_controller
|
47
|
+
controller_class = controller_name.split('_').collect(&:capitalize).join # PostsController
|
48
|
+
code = "#{controller_class}.new(event, context).#{meth}" # PostsController.new(event, context).create
|
49
|
+
|
50
|
+
{path: path, code: code, class_name: controller_class}
|
51
|
+
end
|
52
|
+
end
|
data/lib/lam/util.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Lam::Util
|
2
|
+
# Ensures trailing slash
|
3
|
+
# Useful for appending a './' in front of a path or leaving it alone.
|
4
|
+
# Returns: '/path/with/trailing/slash/' or './'
|
5
|
+
@@root = nil
|
6
|
+
def root
|
7
|
+
return @@root if @@root
|
8
|
+
@@root = ENV['PROJECT_ROOT'].to_s
|
9
|
+
@@root = '.' if @@root == ''
|
10
|
+
@@root = "#{@@root}/" unless @@root.ends_with?('/')
|
11
|
+
@@root
|
12
|
+
end
|
13
|
+
end
|
data/lib/lam/version.rb
CHANGED
data/notes/design.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
## Project Structure
|
2
|
+
|
3
|
+
TODO: make this a table
|
4
|
+
|
5
|
+
```sh
|
6
|
+
app/controllers
|
7
|
+
app/workers
|
8
|
+
app/functions
|
9
|
+
config/project.yml
|
10
|
+
config/events.yml
|
11
|
+
config/routes.rb
|
12
|
+
```
|
13
|
+
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
```sh
|
18
|
+
lam build
|
19
|
+
lam deploy
|
20
|
+
```
|
21
|
+
|
22
|
+
## Testing
|
23
|
+
|
24
|
+
Testing controller processing without node shim.
|
25
|
+
|
26
|
+
```
|
27
|
+
lam process controller '{ "we" : "love", "using" : "Lambda" }' '{"test": "1"}' "handlers/controllers/posts.create"
|
28
|
+
```
|
29
|
+
|
30
|
+
Testing the generated node shim handler and the controller processing.
|
31
|
+
|
32
|
+
```
|
33
|
+
cd spec/fixtures/project
|
34
|
+
lam build # generates the handlers
|
35
|
+
node handlers/controllers/posts.js
|
36
|
+
```
|
37
|
+
|
38
|
+
VS
|
39
|
+
|
40
|
+
```sh
|
41
|
+
processors/controller_processor.rb '{ "we" : "love", "using" : "Lambda" }' '{"test": "1"}' "handlers/controllers/posts.create" | jq '.'
|
42
|
+
```
|
43
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# start off at project root
|
2
|
+
|
3
|
+
mkdir -p /tmp/lam_build
|
4
|
+
cp Gemfile* /tmp/lam_build/
|
5
|
+
cd /tmp/lam_build # cd into there to build TravelingRuby
|
6
|
+
|
7
|
+
wget http://d6r77u77i8pq3.cloudfront.net/releases/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz .
|
8
|
+
mkdir -p bundled/ruby # tmp/lam_build/bundled/ruby
|
9
|
+
tar -xvf traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz -C bundled/ruby
|
10
|
+
# ls ruby => bin bin.real info lib
|
11
|
+
# bundled/ruby/bin/ruby -v # works now :)
|
12
|
+
|
13
|
+
# had to modify Gemfile and update the local path for linux
|
14
|
+
bundle install --path bundled/gems
|
15
|
+
|
16
|
+
# DONT THINK THAT I NEED TO COPY THE Gemfile into bundled/gems...
|
17
|
+
# mv Gemfile* bundled/gems/ # copy Gemfile from the project to bundled/gems
|
18
|
+
# IMPORTANT: the Gemfile must be in the same bundled/gems folder
|
19
|
+
|
20
|
+
# now we have both bundled/gems bundled/ruby :)
|
21
|
+
bundled/gems/ruby/2.2.0/bin/print_ruby_info # should work
|
22
|
+
|
23
|
+
|
24
|
+
# Let's move back to the project and test the wrapper, it should work also
|
25
|
+
mv bundled ~/lam-test/lam/spec/fixtures/project/
|
26
|
+
cd ~/lam-test/lam/spec/fixtures/project # back to project root
|
@@ -0,0 +1,103 @@
|
|
1
|
+
### Packaging Gems Info
|
2
|
+
|
3
|
+
### Structure
|
4
|
+
|
5
|
+
This is the structure that TravelingRuby uses in it's tutorial.
|
6
|
+
|
7
|
+
```sh
|
8
|
+
PROJECT/YOUR_BINARY_WRAPPER (hello)
|
9
|
+
PROJECT/lib/ruby/bin/ruby -> PROJECT/lib/ruby/bin.real/ruby
|
10
|
+
PROJECT/lib/vendor/ruby/2.2.0/bin/print_ruby_info # the gem binaries are here
|
11
|
+
```
|
12
|
+
|
13
|
+
* Instead calling the ruby binary `lam process` command directly.
|
14
|
+
* Lam will require 'bundler/setup' so the user's gems will be required properly
|
15
|
+
* Skip the overhead of having another wrapper
|
16
|
+
|
17
|
+
```sh
|
18
|
+
PROJECT/vendor/ruby/2.2.0/bin/lam # the gem binaries are here
|
19
|
+
```
|
20
|
+
|
21
|
+
### Packaging Gems Commands
|
22
|
+
|
23
|
+
```
|
24
|
+
mkdir packaging/tmp
|
25
|
+
cp Gemfile Gemfile.lock packaging/tmp/ # this are from the user's project
|
26
|
+
cd packaging/tmp
|
27
|
+
|
28
|
+
# here's where the gems are instaleld into packaging/vendor/
|
29
|
+
BUNDLE_IGNORE_CONFIG=1 bundle install --path ../vendor --without development
|
30
|
+
# IMPORTANT: Think I'll make the user switch to 2.2.0 and error the build proccess.
|
31
|
+
|
32
|
+
##############
|
33
|
+
I can call ruby bin files directly.
|
34
|
+
I was WRONG. Cannot call gem bin files directly because I need to make sure that
|
35
|
+
bundler/setup gets loaded before calling the gem bin.
|
36
|
+
Tried moving bundler/setup into the lam library itself but get all sorts of warnings.
|
37
|
+
|
38
|
+
hello-1.0.0-linux-x86_64/lib/vendor/ruby/2.2.0/bin/lam help
|
39
|
+
BUT the shabang line has: #!/usr/bin/env ruby2.0 .. but only on linux..
|
40
|
+
Simply cannot rename the darn ruby version folder.
|
41
|
+
#############
|
42
|
+
|
43
|
+
|
44
|
+
cd ../..
|
45
|
+
rm -rf packaging/tmp # remove working space
|
46
|
+
|
47
|
+
# reduce the zip package size!
|
48
|
+
rm -f packaging/vendor/*/*/cache/*
|
49
|
+
```
|
50
|
+
|
51
|
+
Now we can copy over the generated vendored files
|
52
|
+
|
53
|
+
##################################
|
54
|
+
# clean
|
55
|
+
rm -rf packaging/vendor/
|
56
|
+
|
57
|
+
bundle update
|
58
|
+
rake package:linux:x86_64 DIR_ONLY=1
|
59
|
+
|
60
|
+
mkdir packaging/tmp
|
61
|
+
cp Gemfile Gemfile.lock packaging/tmp/
|
62
|
+
cd packaging/tmp
|
63
|
+
BUNDLE_IGNORE_CONFIG=1 bundle install --path ../vendor --without development
|
64
|
+
cd ../..
|
65
|
+
|
66
|
+
cp -pR packaging/vendor hello-1.0.0-linux-x86_64/lib/
|
67
|
+
cp Gemfile Gemfile.lock hello-1.0.0-linux-x86_64/lib/vendor/
|
68
|
+
mkdir hello-1.0.0-linux-x86_64/lib/vendor/.bundle
|
69
|
+
cp packaging/bundler-config hello-1.0.0-linux-x86_64/lib/vendor/.bundle/config
|
70
|
+
|
71
|
+
find . -name print_ruby_info
|
72
|
+
|
73
|
+
|
74
|
+
# Wrapper script `lam`
|
75
|
+
|
76
|
+
```bash
|
77
|
+
#!/bin/bash
|
78
|
+
set -e
|
79
|
+
|
80
|
+
# Figure out where this script is located.
|
81
|
+
SELFDIR="`dirname \"$0\"`"
|
82
|
+
SELFDIR="`cd \"$SELFDIR\" && pwd`"
|
83
|
+
|
84
|
+
# Tell Bundler where the Gemfile and gems are.
|
85
|
+
export BUNDLE_GEMFILE="$SELFDIR/lib/vendor/Gemfile"
|
86
|
+
unset BUNDLE_IGNORE_CONFIG
|
87
|
+
|
88
|
+
# Run the actual app using the bundled Ruby interpreter, with Bundler activated.
|
89
|
+
exec "$SELFDIR/lib/ruby/bin/ruby" -rbundler/setup "$SELFDIR/lib/app/hello.rb"
|
90
|
+
```
|
91
|
+
|
92
|
+
|
93
|
+
### Building Ruby
|
94
|
+
http://cache.ruby-lang.org/pub/ruby/2.2/
|
95
|
+
|
96
|
+
```sh
|
97
|
+
wget http://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.2.tar.gz
|
98
|
+
tar xvfvz ruby-2.2.2.tar.gz
|
99
|
+
cd ruby-2.2.2
|
100
|
+
./configure
|
101
|
+
make
|
102
|
+
sudo make install
|
103
|
+
```
|
@@ -0,0 +1,82 @@
|
|
1
|
+
## Overview
|
2
|
+
|
3
|
+
There are 2 things to point out:
|
4
|
+
|
5
|
+
1. What the user's environment contains - cannot control this, can only suggest
|
6
|
+
2. What the lambda environment contains - can fully control this
|
7
|
+
|
8
|
+
* User can develop with ruby 2.4 and bundle gems and test and be happy. Hopefully they eventually learn to test with ruby 2.2.0 (when they run into bugs).
|
9
|
+
* When `lam build` runs it will bundle it in ruby 2.2.0 though.
|
10
|
+
* When lambda runs it will call `lam` with ruby 2.2.0. The gems will be installed in 2.2.0
|
11
|
+
* Hope all works
|
12
|
+
|
13
|
+
## Download ruby commands
|
14
|
+
|
15
|
+
```sh
|
16
|
+
# linux 64bit
|
17
|
+
wget http://d6r77u77i8pq3.cloudfront.net/releases/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz .
|
18
|
+
mkdir ruby-linux
|
19
|
+
tar -xvf traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz -C ruby-linux
|
20
|
+
# mac
|
21
|
+
wget http://d6r77u77i8pq3.cloudfront.net/releases/traveling-ruby-20150715-2.2.2-osx.tar.gz
|
22
|
+
mkdir ruby-mac
|
23
|
+
tar -xvf traveling-ruby-20150715-2.2.2-osx.tar.gz -C ruby-mac
|
24
|
+
|
25
|
+
# another version
|
26
|
+
mkdir hello-1.0.0-linux-x86_64/lib/ruby && tar -xzf packaging/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz -C hello-1.0.0-linux-x86_64/lib/ruby
|
27
|
+
```
|
28
|
+
|
29
|
+
## Launch Instance for Testing
|
30
|
+
|
31
|
+
```sh
|
32
|
+
aws ec2 run-instances --image-id ami-8c1be5f6 --count 1 --instance-type t2.micro --key-name default --security-groups demo
|
33
|
+
```
|
34
|
+
|
35
|
+
## Tree Structure
|
36
|
+
|
37
|
+
```sh
|
38
|
+
lib/
|
39
|
+
├── app
|
40
|
+
│ └── hello.rb
|
41
|
+
├── ruby
|
42
|
+
│ ├── bin
|
43
|
+
│ │ ├── gem
|
44
|
+
│ │ ├── irb
|
45
|
+
│ │ ├── rake
|
46
|
+
│ │ ├── ruby
|
47
|
+
│ │ └── ruby_environment
|
48
|
+
│ ├── bin.real
|
49
|
+
│ │ ├── bundle
|
50
|
+
│ │ ├── bundler
|
51
|
+
│ │ ├── gem
|
52
|
+
│ │ ├── irb
|
53
|
+
│ │ ├── rake
|
54
|
+
│ │ └── ruby
|
55
|
+
│ └── lib
|
56
|
+
│ └── ruby
|
57
|
+
│ ├── 2.2.0
|
58
|
+
...
|
59
|
+
│ │ └── yaml.rb
|
60
|
+
│ ├── gems
|
61
|
+
│ │ └── 2.2.0
|
62
|
+
│ │ ├── gems
|
63
|
+
│ │ │ ├── attr_extras-5.2.0
|
64
|
+
│ │ │ │ ├── attr_extras.gemspec
|
65
|
+
...
|
66
|
+
│ │ │ ├── bundler-1.9.9
|
67
|
+
...
|
68
|
+
│ │ └── rake-12.2.1.gemspec
|
69
|
+
...
|
70
|
+
└── vendor
|
71
|
+
├── Gemfile
|
72
|
+
├── Gemfile.lock
|
73
|
+
└── ruby
|
74
|
+
└── 2.2.0 <= IMPORTANT: bundler copies gems to folder with running ruby version
|
75
|
+
├── gems
|
76
|
+
│ ├── concurrent-ruby-1.0.5
|
77
|
+
│ ├── faker-1.7.3
|
78
|
+
│ └── i18n-0.9.0
|
79
|
+
...
|
80
|
+
```
|
81
|
+
|
82
|
+
* [Full tree](https://gist.github.com/tongueroo/c42f9d35b15b06eb810802243f4e2f6d)
|
@@ -0,0 +1 @@
|
|
1
|
+
2.2.2
|
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: /Users/tung/src/tongueroo/lam
|
3
|
+
specs:
|
4
|
+
lam (0.0.1)
|
5
|
+
activesupport
|
6
|
+
colorize
|
7
|
+
hashie
|
8
|
+
thor
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activesupport (5.1.4)
|
14
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
|
+
i18n (~> 0.7)
|
16
|
+
minitest (~> 5.1)
|
17
|
+
tzinfo (~> 1.1)
|
18
|
+
colorize (0.8.1)
|
19
|
+
concurrent-ruby (1.0.5)
|
20
|
+
hashie (3.5.6)
|
21
|
+
i18n (0.9.0)
|
22
|
+
concurrent-ruby (~> 1.0)
|
23
|
+
minitest (5.10.3)
|
24
|
+
print_ruby_info (0.0.3)
|
25
|
+
thor (0.20.0)
|
26
|
+
thread_safe (0.3.6)
|
27
|
+
tzinfo (1.2.3)
|
28
|
+
thread_safe (~> 0.1)
|
29
|
+
|
30
|
+
PLATFORMS
|
31
|
+
ruby
|
32
|
+
|
33
|
+
DEPENDENCIES
|
34
|
+
lam!
|
35
|
+
print_ruby_info
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class PostsController < Lam::BaseController
|
2
|
+
def create
|
3
|
+
# render text: "test2" # more consistent for web controllers
|
4
|
+
|
5
|
+
# render returns Lamba Proxy struture for web requests
|
6
|
+
render json: event, status: 200
|
7
|
+
end
|
8
|
+
|
9
|
+
# def update
|
10
|
+
# render json: event, status: 200
|
11
|
+
# end
|
12
|
+
end
|