jets 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +7 -0
  4. data/Gemfile.lock +63 -0
  5. data/Guardfile +19 -9
  6. data/README.md +9 -16
  7. data/jets.gemspec +11 -7
  8. data/lib/jets.rb +11 -0
  9. data/lib/jets/base_controller.rb +54 -0
  10. data/lib/jets/build.rb +46 -0
  11. data/lib/jets/build/handler_generator.rb +46 -0
  12. data/lib/jets/build/lambda_deducer.rb +23 -0
  13. data/lib/jets/build/templates/handler.js +149 -0
  14. data/lib/jets/build/traveling_ruby.rb +133 -0
  15. data/lib/jets/cfn.rb +5 -0
  16. data/lib/jets/cfn/base.rb +17 -0
  17. data/lib/jets/cfn/builder.rb +53 -0
  18. data/lib/jets/cfn/namer.rb +30 -0
  19. data/lib/jets/cli.rb +10 -6
  20. data/lib/jets/cli/help.rb +8 -2
  21. data/lib/jets/process.rb +18 -0
  22. data/lib/jets/process/base_processor.rb +23 -0
  23. data/lib/jets/process/controller_processor.rb +36 -0
  24. data/lib/jets/process/help.rb +11 -0
  25. data/lib/jets/process/processor_deducer.rb +51 -0
  26. data/lib/jets/project.rb +23 -0
  27. data/lib/jets/util.rb +13 -0
  28. data/lib/jets/version.rb +1 -1
  29. data/notes/design.md +107 -0
  30. data/notes/faq.md +3 -0
  31. data/notes/lambda_ruby_info.md +34 -0
  32. data/notes/traveling-ruby-packaging-jets.md +26 -0
  33. data/notes/traveling-ruby-packaging.md +103 -0
  34. data/notes/traveling-ruby-structure.md +6 -0
  35. data/notes/traveling-ruby.md +82 -0
  36. data/spec/fixtures/classes.rb +5 -0
  37. data/spec/fixtures/project/.gitignore +3 -0
  38. data/spec/fixtures/project/.ruby-version +1 -0
  39. data/spec/fixtures/project/Gemfile +4 -0
  40. data/spec/fixtures/project/Gemfile.lock +23 -0
  41. data/spec/fixtures/project/app/controllers/application_controller.rb +2 -0
  42. data/spec/fixtures/project/app/controllers/posts_controller.rb +12 -0
  43. data/spec/fixtures/project/bin/jets +22 -0
  44. data/spec/fixtures/project/config/routes.rb +6 -0
  45. data/spec/fixtures/project/handlers/controllers/posts.js +212 -0
  46. data/spec/lib/cli_spec.rb +5 -4
  47. data/spec/lib/jets/base_controller_spec.rb +18 -0
  48. data/spec/lib/jets/build/handler_generator_spec.rb +20 -0
  49. data/spec/lib/jets/build/lambda_deducer_spec.rb +15 -0
  50. data/spec/lib/jets/build_spec.rb +34 -0
  51. data/spec/lib/jets/cfn/builder_spec.rb +18 -0
  52. data/spec/lib/jets/cfn/namer_spec.rb +16 -0
  53. data/spec/lib/jets/process/controller_processor_spec.rb +22 -0
  54. data/spec/lib/jets/process/infer_spec.rb +24 -0
  55. data/spec/lib/jets/process_spec.rb +18 -0
  56. data/spec/lib/jets/project_spec.rb +14 -0
  57. data/spec/spec_helper.rb +8 -2
  58. metadata +82 -15
@@ -0,0 +1,13 @@
1
+ module Jets::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,3 +1,3 @@
1
1
  module Jets
2
- VERSION = "0.0.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,107 @@
1
+ ## What is Jets?
2
+
3
+ Jet's is a Lambda Framework that allows you to create AWS Lambda serverless applications with ruby. It includes everything required to build a web application and deploy it to AWS Lambda. It also can be used as a cost-effective worker system. For example, it can be used to write "cron" jobs.
4
+
5
+ It is key to conceptually understand AWS Lambda and API Gateway to understand Jets. Jets maps your code to Lambda functions and API Gatway.
6
+
7
+ * **AWS Lambda** is Functions as a Service. It allows you to upload and run functions without worrying about the underlying infrastructure.
8
+ * **API Gateway** is a routing layer for Lambda. You can use it to route url endpoints to your Lambda functions.
9
+
10
+ ## How It Works
11
+
12
+ With Jets, you focus on your business logic and Jet's does the mechanical work. You write controllers, workers and functions and Jets automatically wire these up to Lambda and API Gateway for you.
13
+
14
+ ### What is a Jets controller?
15
+
16
+ A Jets controller handles a web request and rendering a response back to the user. Here's an example
17
+
18
+ `app/controllers/posts_controller.rb`:
19
+
20
+ ```ruby
21
+ class PostsController < Jets::BaseController
22
+ def create
23
+ # event and context is automatically available as a Hash
24
+ # render returns Lambda Proxy struture for web requests
25
+ render json: event, status: 200
26
+ end
27
+
28
+ def update
29
+ render json: event.merge(a: "update"), status: 200
30
+ end
31
+ end
32
+ ```
33
+
34
+ Jets creates up lambda functions for each of the controller public methods above when you run the `jets deploy` command.
35
+
36
+ ### How do I connect API Gateway to the Lambda functions?
37
+
38
+ You can hook the Lambda functions to url endpoints via API Gateway. To route an API Gateway endpoint to the controller action, add the following to your routes file:
39
+
40
+ `config/routes.rb`:
41
+
42
+ ```ruby
43
+ # API Gateway resources are only created if the controller action exists.
44
+ get "posts", to: "posts#index"
45
+ get "posts/:id", to: "posts#show"
46
+ post "posts", to: "posts#create"
47
+ get "posts/:id/edit", to: "posts#edit"
48
+ put "posts", to: "posts#update"
49
+ delete "posts", to: "posts#destroy"
50
+
51
+ resources :posts # macro that will creaet all the routes above
52
+
53
+ any "posts/hot", to: "posts#hot" # GET, POST, PUT, etc request all work
54
+ ```
55
+
56
+ Run the `jets deploy` command to add the routes to API Gateway.
57
+
58
+ ### Project Structure
59
+
60
+ Here's an overview of the project structure.
61
+
62
+ File / Directory | Description
63
+ ------------- | -------------
64
+ app/controllers | controllers code
65
+ app/workers | workers code
66
+ app/functions | functions code
67
+ config/project.yml | project configs
68
+ config/events.yml | events configs
69
+ config/routes.rb | routes
70
+
71
+
72
+ ## Usage
73
+
74
+ ### Quick Start
75
+
76
+ ```sh
77
+ jets deploy
78
+
79
+ jets deploy
80
+ jets deploy function xxx
81
+ jets deploy controller xxx
82
+ jets deploy worker xxx
83
+ ```
84
+
85
+ ### Scaffolding
86
+
87
+
88
+
89
+ ## Under the hood
90
+
91
+ Lambda does not yet support ruby. So Jets uses a node shim and a bundled version of ruby to add support.
92
+
93
+ ## Test
94
+
95
+ Testing controller processing without node shim.
96
+
97
+ ```
98
+ jets process controller '{ "we" : "love", "using" : "Lambda" }' '{"test": "1"}' "handlers/controllers/posts.create"
99
+ ```
100
+
101
+ Testing the generated node shim handler and the controller processing.
102
+
103
+ ```
104
+ cd spec/fixtures/project
105
+ jets build # generates the handlers
106
+ node handlers/controllers/posts.js
107
+ ```
@@ -0,0 +1,3 @@
1
+ Q: Is it slower using a node shim?
2
+ Yes, the node shim adds a little bit of overhead. The overhead is of the node shim is about 500ms with a function configured to use 1.5GB of RAM. If your application requires faster response times than than then you will have to wait for official ruby support from AWS.
3
+
@@ -0,0 +1,34 @@
1
+ ```sh
2
+ RUBY_VERSION 2.2.2
3
+ /var/task/bundled/gems/ruby/2.2.0/gems/bin/print_ruby_info
4
+ LOAD_PATH:
5
+ /var/task/bundled/gems/ruby/2.2.0/gems/print_ruby_info-0.0.3/lib
6
+ /var/task/bundled/gems/ruby/2.2.0/gems/jets-0.1.1/lib
7
+ /var/task/bundled/gems/ruby/2.2.0/gems/thor-0.20.0/lib
8
+ /var/task/bundled/gems/ruby/2.2.0/gems/hashie-3.5.6/lib
9
+ /var/task/bundled/gems/ruby/2.2.0/gems/colorize-0.8.1/lib
10
+ /var/task/bundled/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/gems/bundler-1.9.9/lib
11
+ /var/task/bundled/gems/ruby/2.2.0/gems/activesupport-5.1.4/lib
12
+ /var/task/bundled/gems/ruby/2.2.0/gems/tzinfo-1.2.3/lib
13
+ /var/task/bundled/gems/ruby/2.2.0/gems/thread_safe-0.3.6/lib
14
+ /var/task/bundled/gems/ruby/2.2.0/gems/minitest-5.10.3/lib
15
+ /var/task/bundled/gems/ruby/2.2.0/gems/i18n-0.9.0/lib
16
+ /var/task/bundled/gems/ruby/2.2.0/gems/concurrent-ruby-1.0.5/lib
17
+ /var/task/bundled/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib
18
+ /var/task/bundled/ruby/lib/ruby/site_ruby/2.2.0
19
+ /var/task/bundled/ruby/lib/ruby/site_ruby/2.2.0/x86_64-linux
20
+ /var/task/bundled/ruby/lib/ruby/site_ruby
21
+ /var/task/bundled/ruby/lib/ruby/vendor_ruby/2.2.0
22
+ /var/task/bundled/ruby/lib/ruby/vendor_ruby/2.2.0/x86_64-linux
23
+ /var/task/bundled/ruby/lib/ruby/vendor_ruby
24
+ /var/task/bundled/ruby/lib/ruby/2.2.0
25
+ /var/task/bundled/ruby/lib/ruby/2.2.0/x86_64-linux
26
+ /tmp/ruby/lib/ruby/site_ruby/2.2.0
27
+ /tmp/ruby/lib/ruby/site_ruby/2.2.0/x86_64-linux
28
+ /tmp/ruby/lib/ruby/site_ruby
29
+ /tmp/ruby/lib/ruby/vendor_ruby/2.2.0
30
+ /tmp/ruby/lib/ruby/vendor_ruby/2.2.0/x86_64-linux
31
+ /tmp/ruby/lib/ruby/vendor_ruby
32
+ /tmp/ruby/lib/ruby/2.2.0
33
+ /tmp/ruby/lib/ruby/2.2.0/x86_64-linux
34
+ ```
@@ -0,0 +1,26 @@
1
+ # start off at project root
2
+
3
+ mkdir -p /tmp/jets_build
4
+ cp Gemfile* /tmp/jets_build/
5
+ cd /tmp/jets_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/jets_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 ~/jets-test/jets/spec/fixtures/project/
26
+ cd ~/jets-test/jets/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 `jets process` command directly.
14
+ * Jets 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/jets # 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 jets library itself but get all sorts of warnings.
37
+
38
+ hello-1.0.0-linux-x86_64/lib/vendor/ruby/2.2.0/bin/jets 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 `jets`
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,6 @@
1
+ ## Traveling Ruby Structure
2
+
3
+ * PROJECT/lib/ruby/bin/ruby -> PROJECT/lib/ruby/bin.real/ruby
4
+ * PROJECT/lib/vendor/ruby/2.2.0/bin/jets
5
+ * PROJECT/YOUR_BINARY_WRAPPER
6
+
@@ -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 `jets build` runs it will bundle it in ruby 2.2.0 though.
10
+ * When lambda runs it will call `jets` 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,5 @@
1
+ class CommentsController < Jets::BaseController
2
+ def create; end
3
+ def update; end
4
+ end
5
+
@@ -0,0 +1,3 @@
1
+ vendor
2
+ bundled
3
+ jets.zip
@@ -0,0 +1 @@
1
+ 2.2.2
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "jets", git: "git@github.com:tongueroo/jets.git"
4
+ gem "print_ruby_info" # test
@@ -0,0 +1,23 @@
1
+ GIT
2
+ remote: git@github.com:tongueroo/jets.git
3
+ revision: 93c085671d2fb6de73ef0246ab89a0c7fecc92ea
4
+ specs:
5
+ jets (0.0.1)
6
+ colorize
7
+ hashie
8
+ thor
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ colorize (0.8.1)
14
+ hashie (3.5.6)
15
+ print_ruby_info (0.0.3)
16
+ thor (0.20.0)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ jets!
23
+ print_ruby_info
@@ -0,0 +1,2 @@
1
+ class ApplicationController < Jets::BaseController
2
+ end
@@ -0,0 +1,12 @@
1
+ class PostsController < Jets::BaseController
2
+ def create
3
+ # render text: "test2" # more consistent for web controllers
4
+
5
+ # render returns Lambda Proxy struture for web requests
6
+ render json: event.merge(a: "create"), status: 200
7
+ end
8
+
9
+ def update
10
+ render json: event.merge(a: "update"), status: 200
11
+ end
12
+ end