lam 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -16
  3. data/Gemfile +3 -3
  4. data/README.md +17 -19
  5. data/Rakefile +0 -4
  6. data/bin/console +14 -0
  7. data/bin/setup +8 -0
  8. data/lam.gemspec +20 -18
  9. data/lib/lam.rb +1 -10
  10. data/lib/lam/version.rb +1 -1
  11. metadata +21 -189
  12. data/.rspec +0 -2
  13. data/.ruby-version +0 -1
  14. data/Gemfile.lock +0 -107
  15. data/Guardfile +0 -22
  16. data/LICENSE.txt +0 -22
  17. data/bin/lam +0 -14
  18. data/lib/lam/base_controller.rb +0 -54
  19. data/lib/lam/build.rb +0 -43
  20. data/lib/lam/build/handler_generator.rb +0 -34
  21. data/lib/lam/build/lambda_deducer.rb +0 -47
  22. data/lib/lam/build/templates/handler.js +0 -156
  23. data/lib/lam/build/traveling_ruby.rb +0 -108
  24. data/lib/lam/cli.rb +0 -23
  25. data/lib/lam/cli/help.rb +0 -19
  26. data/lib/lam/command.rb +0 -25
  27. data/lib/lam/process.rb +0 -18
  28. data/lib/lam/process/base_processor.rb +0 -23
  29. data/lib/lam/process/controller_processor.rb +0 -36
  30. data/lib/lam/process/help.rb +0 -11
  31. data/lib/lam/process/processor_deducer.rb +0 -52
  32. data/lib/lam/util.rb +0 -13
  33. data/notes/design.md +0 -43
  34. data/notes/traveling-ruby-packaging-lam.md +0 -26
  35. data/notes/traveling-ruby-packaging.md +0 -103
  36. data/notes/traveling-ruby.md +0 -82
  37. data/spec/fixtures/project/.gitignore +0 -3
  38. data/spec/fixtures/project/.ruby-version +0 -1
  39. data/spec/fixtures/project/Gemfile +0 -4
  40. data/spec/fixtures/project/Gemfile.lock +0 -35
  41. data/spec/fixtures/project/app/controllers/application_controller.rb +0 -2
  42. data/spec/fixtures/project/app/controllers/posts_controller.rb +0 -12
  43. data/spec/fixtures/project/bin/lam +0 -22
  44. data/spec/fixtures/project/handlers/controllers/posts.js +0 -156
  45. data/spec/lib/cli_spec.rb +0 -20
  46. data/spec/lib/lam/base_controller_spec.rb +0 -18
  47. data/spec/lib/lam/build/lambda_deducer_spec.rb +0 -20
  48. data/spec/lib/lam/build_spec.rb +0 -29
  49. data/spec/lib/lam/process/controller_processor_spec.rb +0 -22
  50. data/spec/lib/lam/process/infer_spec.rb +0 -24
  51. data/spec/lib/lam/process_spec.rb +0 -18
  52. data/spec/spec_helper.rb +0 -25
@@ -1,108 +0,0 @@
1
- require "fileutils"
2
- require "open-uri"
3
- require "colorize"
4
-
5
- class Lam::Build
6
- TRAVELING_RUBY_VERSION = 'http://d6r77u77i8pq3.cloudfront.net/releases/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz'.freeze
7
- TEMP_BUILD_DIR = '/tmp/lam_build'.freeze
8
-
9
- class TravelingRuby
10
- def build
11
- if File.exist?("#{Lam.root}bundled")
12
- puts "Ruby bundled already exists."
13
- puts "To force rebundling: rm -rf bundled"
14
- return
15
- end
16
-
17
- check_ruby_version
18
-
19
- FileUtils.mkdir_p(TEMP_BUILD_DIR)
20
- copy_gemfiles
21
-
22
- Dir.chdir(TEMP_BUILD_DIR) do
23
- download_traveling_ruby
24
- unpack_traveling_ruby
25
- bundle_install
26
- end
27
-
28
- move_bundled_to_project
29
- end
30
-
31
- def check_ruby_version
32
- return if ENV['LAM_SKIP_RUBY_CHECK'] # only use if you absolutely need to
33
- traveling_version = TRAVELING_RUBY_VERSION.match(/-((\d+)\.(\d+)\.(\d+))-/)[1]
34
- if RUBY_VERSION != traveling_version
35
- puts "You are using ruby version #{RUBY_VERSION}."
36
- abort("You must use ruby #{traveling_version} to build the project because it's what Traveling Ruby uses.".colorize(:red))
37
- end
38
- end
39
-
40
- def copy_gemfiles
41
- FileUtils.cp("#{Lam.root}Gemfile", "#{TEMP_BUILD_DIR}/")
42
- FileUtils.cp("#{Lam.root}Gemfile.lock", "#{TEMP_BUILD_DIR}/")
43
- end
44
-
45
- def download_traveling_ruby
46
- puts "Downloading traveling ruby from #{traveling_ruby_url}."
47
-
48
- FileUtils.rm_rf("#{TEMP_BUILD_DIR}/#{bundled_ruby_dest}")
49
- File.open(traveling_ruby_tar_file, 'wb') do |saved_file|
50
- # the following "open" is provided by open-uri
51
- open(traveling_ruby_url, 'rb') do |read_file|
52
- saved_file.write(read_file.read)
53
- end
54
- end
55
-
56
- puts 'Download complete.'
57
- end
58
-
59
- def unpack_traveling_ruby
60
- puts 'Unpacking traveling ruby.'
61
-
62
- FileUtils.mkdir_p(bundled_ruby_dest)
63
-
64
- success = system("tar -xzf #{traveling_ruby_tar_file} -C #{bundled_ruby_dest}")
65
- abort('Unpacking traveling ruby failed') unless success
66
- puts 'Unpacking traveling ruby successful.'
67
-
68
- puts 'Removing tar.'
69
- FileUtils.rm_rf(traveling_ruby_tar_file)
70
- end
71
-
72
- def bundle_install
73
- puts 'Installing bundle.'
74
- require "bundler" # dynamicaly require bundler so user can use any bundler
75
- Bundler.with_clean_env do
76
- success = system(
77
- "cd #{TEMP_BUILD_DIR} && " \
78
- 'env BUNDLE_IGNORE_CONFIG=1 bundle install --path bundled/gems --without development'
79
- )
80
-
81
- abort('Bundle install failed, exiting.') unless success
82
- end
83
-
84
- puts 'Bundle install success.'
85
- end
86
-
87
- def move_bundled_to_project
88
- if File.exist?("#{Lam.root}bundled")
89
- puts "Removing current bundled folder"
90
- FileUtils.rm_rf("#{Lam.root}bundled")
91
- end
92
- puts "Moving bundled ruby to your project."
93
- FileUtils.mv("#{TEMP_BUILD_DIR}/bundled", Lam.root)
94
- end
95
-
96
- def bundled_ruby_dest
97
- "bundled/ruby"
98
- end
99
-
100
- def traveling_ruby_url
101
- TRAVELING_RUBY_VERSION
102
- end
103
-
104
- def traveling_ruby_tar_file
105
- File.basename(traveling_ruby_url)
106
- end
107
- end
108
- end
@@ -1,23 +0,0 @@
1
- require "thor"
2
- require "lam/cli/help"
3
-
4
- module Lam
5
-
6
- class CLI < Command
7
- class_option :verbose, type: :boolean
8
- class_option :noop, type: :boolean
9
-
10
- desc "build", "Builds and prepares project for Lambda"
11
- long_desc Help.build
12
- option :force, type: :boolean, aliases: "-f", desc: "override existing starter files"
13
- option :quiet, type: :boolean, aliases: "-q", desc: "silence the output"
14
- option :format, type: :string, default: "yaml", desc: "starter project template format: json or yaml"
15
- def build
16
- Lam::Build.new(options).run
17
- end
18
-
19
- desc "process TYPE", "process subcommand tasks"
20
- long_desc Help.process
21
- subcommand "process", Lam::Process
22
- end
23
- end
@@ -1,19 +0,0 @@
1
- module Lam
2
- class CLI < Command
3
- class Help
4
- class << self
5
- def build
6
- <<-EOL
7
- Builds and prepares project for AWS Lambda. Generates a node shim and vendors Traveling Ruby. Creates a zip file to be uploaded to Lambda for each handler.
8
- EOL
9
- end
10
-
11
- def process
12
- <<-EOL
13
- TODO: update process help menu
14
- EOL
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,25 +0,0 @@
1
- require "thor"
2
-
3
- module Lam
4
- class Command < Thor
5
- class << self
6
- def dispatch(m, args, options, config)
7
- # Allow calling for help via:
8
- # lam command help
9
- # lam command -h
10
- # lam command --help
11
- # lam command -D
12
- #
13
- # as well thor's normal way:
14
- #
15
- # lam help command
16
- help_flags = Thor::HELP_MAPPINGS + ["help"]
17
- if args.length > 1 && !(args & help_flags).empty?
18
- args -= help_flags
19
- args.insert(-2, "help")
20
- end
21
- super
22
- end
23
- end
24
- end
25
- end
@@ -1,18 +0,0 @@
1
- class Lam::Process < Lam::Command
2
- autoload :Help, 'lam/process/help'
3
- autoload :ProcessorDeducer, 'lam/process/processor_deducer'
4
- autoload :BaseProcessor, 'lam/process/base_processor'
5
- autoload :ControllerProcessor, 'lam/process/controller_processor'
6
-
7
- class_option :verbose, type: :boolean
8
- class_option :noop, type: :boolean
9
- class_option :project_root, desc: "Project folder. Defaults to current directory", default: "."
10
- class_option :region, desc: "AWS region"
11
-
12
- desc "create STACK", "create a CloudFormation stack"
13
- option :randomize_stack_name, type: :boolean, desc: "tack on random string at the end of the stack name", default: nil
14
- long_desc Help.controller
15
- def controller(event, context, handler)
16
- ControllerProcessor.new(event, context, handler).run
17
- end
18
- end
@@ -1,23 +0,0 @@
1
- require 'json'
2
- require_relative 'processor_deducer'
3
-
4
- # Global overrides for Lambda processing
5
- $stdout.sync = true
6
- # This might seem weird but we want puts to write to stderr which is set in
7
- # the node shim to write to stderr. This directs the output to Lambda logs.
8
- # Printing to stdout can managle up the payload returned from Lambda function.
9
- # This is not desired if you want to return say a json payload to API Gateway
10
- # eventually.
11
- def puts(text)
12
- $stderr.puts(text)
13
- end
14
-
15
- class Lam::Process::BaseProcessor
16
- attr_reader :event, :context, :handler
17
- def initialize(event, context, handler)
18
- # assume valid json from Lambda
19
- @event = JSON.parse(event)
20
- @context = JSON.parse(context)
21
- @handler = handler
22
- end
23
- end
@@ -1,36 +0,0 @@
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
@@ -1,11 +0,0 @@
1
- class Lam::Process::Help
2
- class << self
3
- def controller
4
- <<-EOL
5
- Examples:
6
-
7
- lam process controller '{ "we" : "love", "using" : "Lambda" }' '{"test": "1"}' "handlers/controllers/posts.create"
8
- EOL
9
- end
10
- end
11
- end
@@ -1,52 +0,0 @@
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
@@ -1,13 +0,0 @@
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
@@ -1,43 +0,0 @@
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
-
@@ -1,26 +0,0 @@
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
@@ -1,103 +0,0 @@
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
- ```