jets 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/bin/commit_docs.sh +26 -0
  3. data/.circleci/config.yml +126 -0
  4. data/.codebuild/README.md +57 -0
  5. data/.codebuild/bin/jets +3 -0
  6. data/.codebuild/buildspec-base.yml +14 -0
  7. data/.codebuild/integration.sh +54 -0
  8. data/.codebuild/jets.postman_collection.json +323 -0
  9. data/.codebuild/scripts/install-docker.sh +12 -0
  10. data/.codebuild/scripts/install-dynamodb-local.sh +22 -0
  11. data/.codebuild/scripts/install-java.sh +20 -0
  12. data/.codebuild/scripts/install-node.sh +4 -0
  13. data/.gitignore +3 -0
  14. data/.gitmodules +9 -0
  15. data/.python-version +1 -0
  16. data/.rspec +2 -0
  17. data/.ruby-version +1 -1
  18. data/CHANGELOG.md +3 -0
  19. data/Dockerfile +16 -0
  20. data/Dockerfile.base +53 -0
  21. data/Gemfile +8 -1
  22. data/Gemfile.lock +132 -28
  23. data/LICENSE.txt +1 -1
  24. data/Procfile +2 -0
  25. data/README.md +116 -17
  26. data/Rakefile +6 -0
  27. data/buildspec.yml +18 -0
  28. data/exe/jets +14 -0
  29. data/jets.gemspec +31 -3
  30. data/lib/jets.rb +56 -8
  31. data/lib/jets/application.rb +121 -0
  32. data/lib/jets/application/middleware.rb +23 -0
  33. data/lib/jets/aws_services.rb +71 -0
  34. data/lib/jets/booter.rb +95 -0
  35. data/lib/jets/builders.rb +6 -0
  36. data/lib/jets/builders/code_builder.rb +431 -0
  37. data/lib/jets/builders/deducer.rb +73 -0
  38. data/lib/jets/builders/gem_replacer.rb +154 -0
  39. data/lib/jets/builders/handler_generator.rb +76 -0
  40. data/lib/jets/builders/node-hello.js +73 -0
  41. data/lib/jets/builders/node-shim.js +151 -0
  42. data/lib/jets/cfn.rb +5 -4
  43. data/lib/jets/cfn/ship.rb +178 -0
  44. data/lib/jets/cfn/status.rb +208 -0
  45. data/lib/jets/cfn/template_builders.rb +21 -0
  46. data/lib/jets/cfn/template_builders/api_gateway_builder.rb +73 -0
  47. data/lib/jets/cfn/template_builders/api_gateway_deployment_builder.rb +38 -0
  48. data/lib/jets/cfn/template_builders/base_child_builder.rb +38 -0
  49. data/lib/jets/cfn/template_builders/controller_builder.rb +107 -0
  50. data/lib/jets/cfn/template_builders/function_builder.rb +20 -0
  51. data/lib/jets/cfn/template_builders/function_properties.rb +6 -0
  52. data/lib/jets/cfn/template_builders/function_properties/base_builder.rb +106 -0
  53. data/lib/jets/cfn/template_builders/function_properties/node_builder.rb +12 -0
  54. data/lib/jets/cfn/template_builders/function_properties/python_builder.rb +12 -0
  55. data/lib/jets/cfn/template_builders/function_properties/ruby_builder.rb +13 -0
  56. data/lib/jets/cfn/template_builders/interface.rb +91 -0
  57. data/lib/jets/cfn/template_builders/job_builder.rb +63 -0
  58. data/lib/jets/cfn/template_builders/parent_builder.rb +97 -0
  59. data/lib/jets/cfn/template_builders/rule_builder.rb +55 -0
  60. data/lib/jets/cfn/template_builders/templates/minimal-stack.yml +45 -0
  61. data/lib/jets/cfn/template_mappers.rb +23 -0
  62. data/lib/jets/cfn/template_mappers/api_gateway_deployment_mapper.rb +48 -0
  63. data/lib/jets/cfn/template_mappers/api_gateway_mapper.rb +4 -0
  64. data/lib/jets/cfn/template_mappers/child_mapper.rb +41 -0
  65. data/lib/jets/cfn/template_mappers/config_rule_mapper.rb +34 -0
  66. data/lib/jets/cfn/template_mappers/controller_mapper.rb +36 -0
  67. data/lib/jets/cfn/template_mappers/events_rule_mapper.rb +40 -0
  68. data/lib/jets/cfn/template_mappers/function_mapper.rb +4 -0
  69. data/lib/jets/cfn/template_mappers/gateway_method_mapper.rb +56 -0
  70. data/lib/jets/cfn/template_mappers/gateway_resource_mapper.rb +62 -0
  71. data/lib/jets/cfn/template_mappers/job_mapper.rb +4 -0
  72. data/lib/jets/cfn/template_mappers/lambda_function_mapper.rb +50 -0
  73. data/lib/jets/cfn/template_mappers/rule_mapper.rb +5 -0
  74. data/lib/jets/cli.rb +180 -15
  75. data/lib/jets/commands.rb +22 -0
  76. data/lib/jets/commands/base.rb +151 -0
  77. data/lib/jets/commands/build.rb +186 -0
  78. data/lib/jets/commands/call.rb +175 -0
  79. data/lib/jets/commands/call/anonymous_guesser.rb +96 -0
  80. data/lib/jets/commands/call/autoload_guesser.rb +112 -0
  81. data/lib/jets/commands/call/base_guesser.rb +33 -0
  82. data/lib/jets/commands/call/guesser.rb +51 -0
  83. data/lib/jets/commands/console.rb +12 -0
  84. data/lib/jets/commands/db.rb +15 -0
  85. data/lib/jets/commands/db/environment-task.rake +3 -0
  86. data/lib/jets/commands/db/tasks.rb +30 -0
  87. data/lib/jets/commands/dbconsole.rb +131 -0
  88. data/lib/jets/commands/delete.rb +119 -0
  89. data/lib/jets/commands/deploy.rb +53 -0
  90. data/lib/jets/commands/dynamodb.rb +22 -0
  91. data/lib/jets/commands/dynamodb/migrate.rb +9 -0
  92. data/lib/jets/commands/dynamodb/migrator.rb +36 -0
  93. data/lib/jets/commands/help.rb +9 -0
  94. data/lib/jets/commands/help/build.md +1 -0
  95. data/lib/jets/commands/help/call.md +55 -0
  96. data/lib/jets/commands/help/console.md +4 -0
  97. data/lib/jets/commands/help/db/generate.md +8 -0
  98. data/lib/jets/commands/help/dbconsole.md +5 -0
  99. data/lib/jets/commands/help/delete.md +9 -0
  100. data/lib/jets/commands/help/deploy.md +5 -0
  101. data/lib/jets/commands/help/dynamodb/generate.md +50 -0
  102. data/lib/jets/commands/help/dynamodb/migrate.md +4 -0
  103. data/lib/jets/commands/help/generate.md +5 -0
  104. data/lib/jets/commands/help/new.md +9 -0
  105. data/lib/jets/commands/help/process/controller.md +6 -0
  106. data/lib/jets/commands/help/process/function.md +5 -0
  107. data/lib/jets/commands/help/process/job.md +5 -0
  108. data/lib/jets/commands/help/process/rule.md +5 -0
  109. data/lib/jets/commands/help/routes.md +3 -0
  110. data/lib/jets/commands/help/server.md +6 -0
  111. data/lib/jets/commands/help/status.md +1 -0
  112. data/lib/jets/commands/help/url.md +5 -0
  113. data/lib/jets/commands/main.rb +111 -0
  114. data/lib/jets/commands/markdown.rb +8 -0
  115. data/lib/jets/commands/markdown/creator.rb +58 -0
  116. data/lib/jets/commands/markdown/index.rb +27 -0
  117. data/lib/jets/commands/markdown/page.rb +125 -0
  118. data/lib/jets/commands/markdown/shell.rb +11 -0
  119. data/lib/jets/commands/new.rb +110 -0
  120. data/lib/jets/commands/rake_command.rb +61 -0
  121. data/lib/jets/commands/rake_tasks.rb +45 -0
  122. data/lib/jets/commands/sequence.rb +44 -0
  123. data/lib/jets/commands/stack_info.rb +30 -0
  124. data/lib/jets/commands/templates/skeleton/.env +2 -0
  125. data/lib/jets/commands/templates/skeleton/.env.development.tt +3 -0
  126. data/lib/jets/commands/templates/skeleton/.env.test +3 -0
  127. data/lib/jets/commands/templates/skeleton/.gitignore +14 -0
  128. data/lib/jets/commands/templates/skeleton/.jetskeep +1 -0
  129. data/lib/jets/commands/templates/skeleton/Gemfile.tt +27 -0
  130. data/lib/jets/commands/templates/skeleton/Procfile +7 -0
  131. data/lib/jets/commands/templates/skeleton/README.md +4 -0
  132. data/lib/jets/commands/templates/skeleton/Rakefile +2 -0
  133. data/lib/jets/commands/templates/skeleton/app/controllers/application_controller.rb +2 -0
  134. data/lib/jets/commands/templates/skeleton/app/helpers/application_helper.rb +2 -0
  135. data/lib/jets/commands/templates/skeleton/app/jobs/application_job.rb +2 -0
  136. data/lib/jets/commands/templates/skeleton/app/models/application_item.rb +2 -0
  137. data/lib/jets/commands/templates/skeleton/app/models/application_record.rb +3 -0
  138. data/lib/jets/commands/templates/skeleton/app/views/layouts/application.html.erb.tt +24 -0
  139. data/lib/jets/commands/templates/skeleton/bin/ruby_server +18 -0
  140. data/lib/jets/commands/templates/skeleton/bin/ruby_server.rb +2 -0
  141. data/lib/jets/commands/templates/skeleton/config.ru +4 -0
  142. data/lib/jets/commands/templates/skeleton/config/application.rb.tt +26 -0
  143. data/lib/jets/commands/templates/skeleton/config/database.yml.tt +27 -0
  144. data/lib/jets/commands/templates/skeleton/config/dynamodb.yml +25 -0
  145. data/lib/jets/commands/templates/skeleton/config/routes.rb +8 -0
  146. data/lib/jets/commands/templates/skeleton/db/.gitkeep +0 -0
  147. data/lib/jets/commands/templates/skeleton/public/404.html +67 -0
  148. data/lib/jets/commands/templates/skeleton/public/422.html +67 -0
  149. data/lib/jets/commands/templates/skeleton/public/500.html +66 -0
  150. data/lib/jets/commands/templates/skeleton/public/favicon.ico +0 -0
  151. data/lib/jets/commands/templates/skeleton/public/index.html.tt +79 -0
  152. data/lib/jets/commands/templates/skeleton/spec/controllers/posts_controller_spec.rb +18 -0
  153. data/lib/jets/commands/templates/skeleton/spec/fixtures/payloads/posts-index.json +51 -0
  154. data/lib/jets/commands/templates/skeleton/spec/fixtures/payloads/posts-show.json +53 -0
  155. data/lib/jets/commands/templates/skeleton/spec/spec_helper.rb.tt +27 -0
  156. data/lib/jets/commands/templates/webpacker/app/javascript/packs/application.js.tt +14 -0
  157. data/lib/jets/commands/templates/webpacker/app/javascript/packs/theme.scss.tt +24 -0
  158. data/lib/jets/commands/templates/webpacker/app/javascript/src/jets/crud.js +87 -0
  159. data/lib/jets/commands/url.rb +45 -0
  160. data/lib/jets/commands/webpacker_template.rb +19 -0
  161. data/lib/jets/controller.rb +9 -0
  162. data/lib/jets/controller/base.rb +50 -0
  163. data/lib/jets/controller/callbacks.rb +43 -0
  164. data/lib/jets/controller/layout.rb +17 -0
  165. data/lib/jets/controller/params.rb +53 -0
  166. data/lib/jets/controller/redirection.rb +55 -0
  167. data/lib/jets/controller/renderers.rb +5 -0
  168. data/lib/jets/controller/renderers/aws_proxy_renderer.rb +69 -0
  169. data/lib/jets/controller/renderers/base_renderer.rb +16 -0
  170. data/lib/jets/controller/renderers/template_renderer.rb +107 -0
  171. data/lib/jets/controller/rendering.rb +80 -0
  172. data/lib/jets/controller/request.rb +55 -0
  173. data/lib/jets/core.rb +81 -0
  174. data/lib/jets/default/application.rb +20 -0
  175. data/lib/jets/dotenv.rb +37 -0
  176. data/lib/jets/erb.rb +51 -0
  177. data/lib/jets/generator.rb +40 -0
  178. data/lib/jets/generator/templates/erb/controller/view.html.erb +2 -0
  179. data/lib/jets/generator/templates/erb/scaffold/_form.html.erb +39 -0
  180. data/lib/jets/generator/templates/erb/scaffold/edit.html.erb +6 -0
  181. data/lib/jets/generator/templates/erb/scaffold/index.html.erb +29 -0
  182. data/lib/jets/generator/templates/erb/scaffold/new.html.erb +5 -0
  183. data/lib/jets/generator/templates/erb/scaffold/show.html.erb +9 -0
  184. data/lib/jets/generator/templates/rails/assets/javascript.js +2 -0
  185. data/lib/jets/generator/templates/rails/assets/stylesheet.css +4 -0
  186. data/lib/jets/generator/templates/rails/controller/controller.rb +13 -0
  187. data/lib/jets/generator/templates/rails/helper/helper.rb +4 -0
  188. data/lib/jets/generator/templates/rails/scaffold/scaffold.css +80 -0
  189. data/lib/jets/generator/templates/rails/scaffold_controller/api_controller.rb +62 -0
  190. data/lib/jets/generator/templates/rails/scaffold_controller/controller.rb +71 -0
  191. data/lib/jets/internal/app/controllers/jets/public_controller.rb +30 -0
  192. data/lib/jets/internal/app/controllers/jets/public_controller/python/show.py +47 -0
  193. data/lib/jets/internal/app/controllers/jets/public_controller/python/show.pyc +0 -0
  194. data/lib/jets/internal/app/controllers/jets/welcome_controller.rb +22 -0
  195. data/lib/jets/internal/app/controllers/jets/welcome_controller/python/index.py +24 -0
  196. data/lib/jets/internal/app/jobs/jets/preheat_job.rb +52 -0
  197. data/lib/jets/job.rb +5 -0
  198. data/lib/jets/job/base.rb +29 -0
  199. data/lib/jets/job/dsl.rb +58 -0
  200. data/lib/jets/job/task.rb +17 -0
  201. data/lib/jets/klass.rb +71 -0
  202. data/lib/jets/lambda.rb +18 -0
  203. data/lib/jets/lambda/dsl.rb +153 -0
  204. data/lib/jets/lambda/function.rb +29 -0
  205. data/lib/jets/lambda/function_constructor.rb +60 -0
  206. data/lib/jets/lambda/functions.rb +22 -0
  207. data/lib/jets/lambda/task.rb +77 -0
  208. data/lib/jets/naming.rb +61 -0
  209. data/lib/jets/pascalize.rb +30 -0
  210. data/lib/jets/poly_fun.rb +61 -0
  211. data/lib/jets/poly_fun/base_executor.rb +129 -0
  212. data/lib/jets/poly_fun/lambda_executor.rb +16 -0
  213. data/lib/jets/poly_fun/node_error.rb +8 -0
  214. data/lib/jets/poly_fun/node_executor.rb +54 -0
  215. data/lib/jets/poly_fun/python_error.rb +8 -0
  216. data/lib/jets/poly_fun/python_executor.rb +23 -0
  217. data/lib/jets/preheat.rb +72 -0
  218. data/lib/jets/processors.rb +4 -0
  219. data/lib/jets/processors/deducer.rb +54 -0
  220. data/lib/jets/processors/main_processor.rb +57 -0
  221. data/lib/jets/rails_overrides.rb +4 -0
  222. data/lib/jets/rails_overrides/asset_tag_helper.rb +41 -0
  223. data/lib/jets/rails_overrides/common_methods.rb +13 -0
  224. data/lib/jets/rails_overrides/rendering_helper.rb +26 -0
  225. data/lib/jets/rails_overrides/url_helper.rb +26 -0
  226. data/lib/jets/route.rb +145 -0
  227. data/lib/jets/router.rb +115 -0
  228. data/lib/jets/ruby_server.rb +91 -0
  229. data/lib/jets/rule.rb +5 -0
  230. data/lib/jets/rule/base.rb +19 -0
  231. data/lib/jets/rule/dsl.rb +64 -0
  232. data/lib/jets/rule/task.rb +44 -0
  233. data/lib/jets/server.rb +16 -0
  234. data/lib/jets/server/api_gateway.rb +39 -0
  235. data/lib/jets/server/lambda_aws_proxy.rb +122 -0
  236. data/lib/jets/server/route_matcher.rb +96 -0
  237. data/lib/jets/server/timing_middleware.rb +16 -0
  238. data/lib/jets/server/webpacker_setup.rb +7 -0
  239. data/lib/jets/timing.rb +65 -0
  240. data/lib/jets/timing/report.rb +82 -0
  241. data/lib/jets/util.rb +7 -12
  242. data/lib/jets/version.rb +1 -1
  243. data/support/clean +3 -0
  244. data/support/console +3 -0
  245. metadata +473 -76
  246. data/bin/jets +0 -14
  247. data/lib/jets/base_controller.rb +0 -54
  248. data/lib/jets/build.rb +0 -46
  249. data/lib/jets/build/handler_generator.rb +0 -46
  250. data/lib/jets/build/lambda_deducer.rb +0 -23
  251. data/lib/jets/build/templates/handler.js +0 -149
  252. data/lib/jets/build/traveling_ruby.rb +0 -133
  253. data/lib/jets/cfn/base.rb +0 -17
  254. data/lib/jets/cfn/builder.rb +0 -53
  255. data/lib/jets/cfn/namer.rb +0 -30
  256. data/lib/jets/cli/help.rb +0 -19
  257. data/lib/jets/command.rb +0 -25
  258. data/lib/jets/process.rb +0 -18
  259. data/lib/jets/process/base_processor.rb +0 -23
  260. data/lib/jets/process/controller_processor.rb +0 -36
  261. data/lib/jets/process/help.rb +0 -11
  262. data/lib/jets/process/processor_deducer.rb +0 -51
  263. data/lib/jets/project.rb +0 -23
  264. data/notes/design.md +0 -107
  265. data/notes/faq.md +0 -3
  266. data/notes/lambda_ruby_info.md +0 -34
  267. data/notes/traveling-ruby-packaging-jets.md +0 -26
  268. data/notes/traveling-ruby-packaging.md +0 -103
  269. data/notes/traveling-ruby-structure.md +0 -6
  270. data/notes/traveling-ruby.md +0 -82
  271. data/spec/fixtures/classes.rb +0 -5
  272. data/spec/fixtures/project/.gitignore +0 -3
  273. data/spec/fixtures/project/.ruby-version +0 -1
  274. data/spec/fixtures/project/Gemfile +0 -4
  275. data/spec/fixtures/project/Gemfile.lock +0 -23
  276. data/spec/fixtures/project/app/controllers/application_controller.rb +0 -2
  277. data/spec/fixtures/project/app/controllers/posts_controller.rb +0 -12
  278. data/spec/fixtures/project/bin/jets +0 -22
  279. data/spec/fixtures/project/config/routes.rb +0 -6
  280. data/spec/fixtures/project/handlers/controllers/posts.js +0 -212
  281. data/spec/lib/cli_spec.rb +0 -20
  282. data/spec/lib/jets/base_controller_spec.rb +0 -18
  283. data/spec/lib/jets/build/handler_generator_spec.rb +0 -20
  284. data/spec/lib/jets/build/lambda_deducer_spec.rb +0 -15
  285. data/spec/lib/jets/build_spec.rb +0 -34
  286. data/spec/lib/jets/cfn/builder_spec.rb +0 -18
  287. data/spec/lib/jets/cfn/namer_spec.rb +0 -16
  288. data/spec/lib/jets/process/controller_processor_spec.rb +0 -22
  289. data/spec/lib/jets/process/infer_spec.rb +0 -24
  290. data/spec/lib/jets/process_spec.rb +0 -18
  291. data/spec/lib/jets/project_spec.rb +0 -14
  292. data/spec/spec_helper.rb +0 -28
@@ -0,0 +1,115 @@
1
+ require 'text-table'
2
+
3
+ module Jets
4
+ class Router
5
+ attr_reader :routes
6
+ def initialize
7
+ @routes = []
8
+ end
9
+
10
+ def draw(&block)
11
+ instance_eval(&block)
12
+ end
13
+
14
+ # Methods supported by API Gateway
15
+ %w[any delete get head options patch post put].each do |method_name|
16
+ define_method method_name do |path, options|
17
+ create_route(options.merge(path: path, method: __method__))
18
+ end
19
+ end
20
+
21
+ # resources macro expands to all the routes
22
+ def resources(name)
23
+ get "#{name}", to: "#{name}#index"
24
+ get "#{name}/new", to: "#{name}#new"
25
+ get "#{name}/:id", to: "#{name}#show"
26
+ post "#{name}", to: "#{name}#create"
27
+ get "#{name}/:id/edit", to: "#{name}#edit"
28
+ put "#{name}/:id", to: "#{name}#update"
29
+ delete "#{name}/:id", to: "#{name}#delete"
30
+ end
31
+
32
+ def create_route(options)
33
+ @routes << Route.new(options)
34
+ end
35
+
36
+ # root "posts#index"
37
+ def root(to)
38
+ @routes << Route.new(path: '', to: to, method: :get, root: true)
39
+ end
40
+
41
+ # Useful for creating API Gateway Resources
42
+ def all_paths
43
+ results = []
44
+ paths = routes.map(&:path)
45
+ paths.each do |p|
46
+ sub_paths = []
47
+ parts = p.split('/')
48
+ until parts.empty?
49
+ parts.pop
50
+ sub_path = parts.join('/')
51
+ sub_paths << sub_path unless sub_path == ''
52
+ end
53
+ results += sub_paths
54
+ end
55
+ @all_paths = (results + paths).sort.uniq
56
+ end
57
+
58
+ # Useful for RouterMatcher
59
+ #
60
+ # Precedence:
61
+ # 1. Routes with no captures get highest precedence: posts/new
62
+ # 2. Then consider the routes with captures: post/:id
63
+ # 3. Last consider the routes with wildcards: *catchall
64
+ #
65
+ # Within these 2 groups we consider the routes with the longest path first
66
+ # since posts/:id and posts/:id/edit can both match.
67
+ def ordered_routes
68
+ length = Proc.new { |r| r.path.length * -1 }
69
+ capture_routes = routes.select { |r| r.path.include?(':') }.sort_by(&length)
70
+ wildcard_routes = routes.select { |r| r.path.include?('*') }.sort_by(&length)
71
+ simple_routes = (routes - capture_routes - wildcard_routes).sort_by(&length)
72
+ simple_routes + capture_routes + wildcard_routes
73
+ end
74
+
75
+ def self.has_controller?(name)
76
+ routes.detect { |r| r.controller_name == name }
77
+ end
78
+
79
+ # Class methods
80
+ def self.draw
81
+ drawn_router
82
+ end
83
+
84
+ @@drawn_router = nil
85
+ def self.drawn_router
86
+ return @@drawn_router if @@drawn_router
87
+
88
+ router = Jets.application.routes
89
+ @@drawn_router = router
90
+ end
91
+
92
+ def self.routes
93
+ drawn_router.routes
94
+ end
95
+
96
+ # Returns all paths including subpaths.
97
+ # Example:
98
+ # Input: ["posts/:id/edit"]
99
+ # Output: ["posts", "posts/:id", "posts/:id/edit"]
100
+ def self.all_paths
101
+ drawn_router.all_paths
102
+ end
103
+
104
+ def self.routes_help
105
+ return "Your routes table is empty." if routes.empty?
106
+
107
+ table = Text::Table.new
108
+ table.head = %w[Verb Path Controller#action]
109
+ routes.each do |route|
110
+ table.rows << [route.method, route.path, route.to]
111
+ end
112
+ table
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,91 @@
1
+ require 'socket'
2
+ require 'json'
3
+
4
+ # https://ruby-doc.org/stdlib-2.3.0/libdoc/socket/rdoc/TCPServer.html
5
+ # https://stackoverflow.com/questions/806267/how-to-fire-and-forget-a-subprocess
6
+ #
7
+ # There's a generated bin/ruby_server which calls bin/ruby_server.rb as part of the
8
+ # starter project template. Usage:
9
+ #
10
+ # bin/ruby_server # background
11
+ # FOREGROUND=1 bin/ruby_server # foreground
12
+ #
13
+ module Jets
14
+ class RubyServer
15
+ PORT = 8080
16
+
17
+ def run
18
+ $stdout.sync = true
19
+ Jets.boot # outside of child process for COW
20
+
21
+ # INT - ^C
22
+ trap('INT') do
23
+ puts "Shutting down ruby_server.rb..."
24
+ sleep 0.1
25
+ exit
26
+ end
27
+ if ENV['FOREGROUND'] # Usage above
28
+ serve
29
+ return
30
+ end
31
+
32
+ # Reaching here means we'll run the server in the background
33
+ pid = Process.fork
34
+ if pid.nil?
35
+ serve
36
+ else
37
+ # parent process
38
+ Process.detach(pid)
39
+ end
40
+ end
41
+
42
+ def serve
43
+ # child process
44
+ server = TCPServer.new(8080) # Server bind to port 8080
45
+ puts "TCPServer started on port #{PORT}"
46
+ input_completed = false
47
+ loop do
48
+ event, handler = nil, nil
49
+ client = server.accept # Wait for a client to connect
50
+ unless input_completed
51
+ event = client.gets.strip # text
52
+ # puts event # uncomment for debugging, Jets has changed stdout to stderr
53
+ handler = client.gets.strip # text
54
+ # puts handler # uncomment for debugging, Jets has changed stdout to stderr
55
+ input_completed = true
56
+ end
57
+
58
+ result = event['_prewarm'] ?
59
+ prewarm_request(event) :
60
+ standard_request(event, '{}', handler)
61
+
62
+ client.puts(result)
63
+ client.close
64
+ input_completed = false
65
+ end
66
+ end
67
+
68
+ def prewarm_request(event)
69
+ # JSON.dump("prewarmed_at" => Time.now.to_s)
70
+ %Q|{"prewarmed_at":"#{Time.now.to_s}"}| # raw json for speed
71
+ end
72
+
73
+ def standard_request(event, context, handler)
74
+ Jets::Processors::MainProcessor.new(
75
+ event,
76
+ context,
77
+ handler).run
78
+ rescue Exception => e
79
+ JSON.dump(
80
+ "stackTrace" => e.backtrace,
81
+ "errorMessage" => e.message,
82
+ "errorType" => "RubyError",
83
+ )
84
+ end
85
+
86
+ def self.run
87
+ new.run
88
+ end
89
+ end
90
+ end
91
+
@@ -0,0 +1,5 @@
1
+ class Jets::Rule
2
+ autoload :Dsl, "jets/rule/dsl"
3
+ autoload :Base, "jets/rule/base"
4
+ autoload :Task, "jets/rule/task"
5
+ end
@@ -0,0 +1,19 @@
1
+ require 'json'
2
+
3
+ # Base public methods get turned into Lambda functions.
4
+ #
5
+ # Jets::Rule::Base < Jets::Lambda::Functions
6
+ # Both Jets::Rule::Base and Jets::Lambda::Functions have Dsl modules included.
7
+ # So the Jets::Rule::Dsl overrides some of the Jets::Lambda::Functions behavior.
8
+ class Jets::Rule
9
+ class Base < Jets::Lambda::Functions
10
+ include Dsl
11
+
12
+ class << self
13
+ def process(event, context, meth)
14
+ job = new(event, context, meth)
15
+ job.send(meth)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,64 @@
1
+ # Jets::Rule::Base < Jets::Lambda::Functions
2
+ # Both Jets::Rule::Base and Jets::Lambda::Functions have Dsl modules included.
3
+ # So the Jets::Rule::Dsl overrides some of the Jets::Lambda::Functions behavior.
4
+ module Jets::Rule::Dsl
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class << self
9
+ # Allows for different types of values. Examples:
10
+ #
11
+ # String: scope "AWS::EC2::SecurityGroup"
12
+ # Array: scope ["AWS::EC2::SecurityGroup"]
13
+ # Hash: scope {"ComplianceResourceTypes" => ["AWS::EC2::SecurityGroup"]}
14
+ def scope(value)
15
+ scope = case value
16
+ when String
17
+ {"ComplianceResourceTypes" => [value]}
18
+ when Array
19
+ {"ComplianceResourceTypes" => value}
20
+ else # default to hash
21
+ value
22
+ end
23
+
24
+ config_rule(scope: scope)
25
+ end
26
+
27
+ def config_rule_name(value)
28
+ config_rule(config_rule_name: value)
29
+ end
30
+
31
+ def description(value)
32
+ config_rule(description: value)
33
+ end
34
+ alias_method :desc, :description
35
+
36
+ def input_parameters(value)
37
+ config_rule(input_parameters: value)
38
+ end
39
+
40
+ def maximum_execution_frequency(value)
41
+ config_rule(maximum_execution_frequency: value)
42
+ end
43
+
44
+ # not really meant to be used but provided for completeness
45
+ def source(value)
46
+ config_rule(source: value)
47
+ end
48
+
49
+ def config_rule(options={})
50
+ @config_rule ||= {}
51
+ @config_rule.deep_merge!(options)
52
+ end
53
+
54
+ # Override register_task.
55
+ # Creates instances of Rule::Task instead of a Lambda::Task
56
+ # Also adds the config_rule option that is specific to Rule classes
57
+ def register_task(meth, lang=:ruby)
58
+ all_tasks[meth] = Jets::Rule::Task.new(self.name, meth,
59
+ properties: @properties, config_rule: @config_rule, lang: lang)
60
+ true
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,44 @@
1
+ class Jets::Rule::Task < Jets::Lambda::Task
2
+ attr_reader :config_rule
3
+ def initialize(class_name, meth, options={})
4
+ super
5
+ @config_rule = options[:config_rule] || {}
6
+ end
7
+
8
+ def config_rule_name
9
+ @properties[:config_rule_name] || conventional_config_rule_name
10
+ end
11
+
12
+ def conventional_config_rule_name
13
+ name_without_rule = @class_name.underscore.gsub(/_rule$/,'')
14
+ "#{name_without_rule}_#{@meth}".dasherize
15
+ end
16
+
17
+ def config_rule_properties
18
+ props = Pascalize.pascalize(@config_rule)
19
+ props = config_rule_defaults.merge(props)
20
+ props
21
+ end
22
+
23
+ def config_rule_defaults
24
+ map = Jets::Cfn::TemplateMappers::ConfigRuleMapper.new(self)
25
+ source_identifier = "!GetAtt #{map.lambda_function_logical_id}.Arn"
26
+ {
27
+ "ConfigRuleName" => config_rule_name,
28
+ "Source" => {
29
+ "Owner" => "CUSTOM_LAMBDA",
30
+ "SourceIdentifier" => source_identifier,
31
+ "SourceDetails" => [
32
+ {
33
+ "EventSource" => "aws.config",
34
+ "MessageType" => "ConfigurationItemChangeNotification"
35
+ },
36
+ {
37
+ "EventSource" => "aws.config",
38
+ "MessageType" => "OversizedConfigurationItemChangeNotification"
39
+ }
40
+ ]
41
+ }
42
+ }
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ require 'rack'
2
+ require 'rack/server'
3
+ require "jets/server/webpacker_setup" if Jets.webpacker?
4
+
5
+ class Jets::Server
6
+ autoload :RouteMatcher, "jets/server/route_matcher"
7
+ autoload :TimingMiddleware, "jets/server/timing_middleware"
8
+ autoload :ApiGateway, "jets/server/api_gateway"
9
+ autoload :LambdaAwsProxy, "jets/server/lambda_aws_proxy"
10
+
11
+ # Use by Jets::Application
12
+ # Where config.ru in the project leads to.
13
+ def self.call(env)
14
+ ApiGateway.call(env)
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ require 'kramdown'
2
+
3
+ class Jets::Server
4
+ class ApiGateway
5
+ def self.call(env)
6
+ Jets.boot
7
+ route = RouteMatcher.new(env).find_route
8
+ if route
9
+ proxy = LambdaAwsProxy.new(route, env)
10
+ triplet = proxy.response
11
+ else
12
+ [404, {'Content-Type' => 'text/html'}, [routes_error_message(env)]]
13
+ end
14
+ end
15
+
16
+ def self.routes_error_message(env)
17
+ message = "<h2>404 Error: Route #{env['PATH_INFO'].sub('/','')} not found</h2>"
18
+ if Jets.env != "production"
19
+ message << "<p>Here are the routes defined in your application:</p>"
20
+ message << "#{routes_table}"
21
+ end
22
+ message
23
+ end
24
+
25
+ # Show pretty route table for user to help with debugging in non-production mode
26
+ def self.routes_table
27
+ routes = Jets::Router.routes
28
+
29
+ return "Your routes table is empty." if routes.empty?
30
+
31
+ text = "Verb | Path | Controller#action\n"
32
+ text << "--- | --- | ---\n"
33
+ routes.each do |route|
34
+ text << "#{route.method} | #{route.path} | #{route.to}\n"
35
+ end
36
+ Kramdown::Document.new(text).to_html
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,122 @@
1
+ require 'cgi'
2
+ require 'stringio'
3
+
4
+ class Jets::Server
5
+ # This doesnt really need to be middleware
6
+ class LambdaAwsProxy
7
+ def initialize(route, env)
8
+ @route = route
9
+ @env = env
10
+ # @env.each do |k,v|
11
+ # puts "#{k}: #{v}"
12
+ # end
13
+ end
14
+
15
+ def response
16
+ event = build_event
17
+ context = {}
18
+
19
+ controller_class = find_controller_class
20
+ controller_action = find_controller_action
21
+
22
+ fun = Jets::PolyFun.new(controller_class, controller_action)
23
+ resp = fun.run(event, context) # check the logs for polymorphic function errors
24
+
25
+ # Map lambda proxy response format to rack format
26
+ status = resp["statusCode"]
27
+ headers = resp["headers"] || {}
28
+ headers = {'Content-Type' => 'text/html'}.merge(headers)
29
+ body = resp["body"]
30
+
31
+ [status, headers, [body]]
32
+ end
33
+
34
+ def build_event
35
+ resource = @route.path(:api_gateway) # posts/{id}/edit
36
+ path = @env['PATH_INFO'].sub('/','') # remove beginning space
37
+ {
38
+ "resource" => "/#{resource}", # "/posts/{id}/edit"
39
+ "path" => @env['PATH_INFO'], # /posts/tung/edit
40
+ "httpMethod" => @env['REQUEST_METHOD'], # GET
41
+ "headers" => request_headers,
42
+ "queryStringParameters" => query_string_parameters,
43
+ "pathParameters" => @route.extract_parameters(path),
44
+ "stageVariables" => nil,
45
+ "requestContext" => {},
46
+ "body" => get_body,
47
+ "isBase64Encoded" => false,
48
+ }
49
+ end
50
+
51
+ # Annoying. The headers part of the AWS Lambda proxy structure
52
+ # does not consisently use the same casing scheme for the header keys.
53
+ # Sometimes it looks like this:
54
+ # Accept-Encoding
55
+ # and sometimes it looks like this:
56
+ # cache-control
57
+ # Map for special cases when the casing doesn't match.
58
+ CASING_MAP = {
59
+ "Cache-Control" => "cache-control",
60
+ "Content-Type" => "content-type",
61
+ "Origin" => "origin",
62
+ "Upgrade-Insecure-Requests" => "upgrade-insecure-requests",
63
+ }
64
+
65
+ def request_headers
66
+ headers = @env.select { |k,v| k =~ /^HTTP_/ }.inject({}) do |h,(k,v)|
67
+ # map things like HTTP_USER_AGENT to "User-Agent"
68
+ key = k.sub('HTTP_','').split('_').map(&:capitalize).join('-')
69
+ h[key] = v
70
+ h
71
+ end
72
+ # Content type is not prepended with HTTP_ but is part of Lambda's event headers thankfully
73
+ headers["Content-Type"] = @env["CONTENT_TYPE"] if @env["CONTENT_TYPE"]
74
+
75
+ # Adjust the casing so it matches the Lambda AWS Proxy's structure
76
+ CASING_MAP.each do |nice_casing, bad_casing|
77
+ if headers.key?(nice_casing)
78
+ headers[bad_casing] = headers.delete(nice_casing)
79
+ end
80
+ end
81
+
82
+ # There are also a couple of other headers that are specific to
83
+ # AWS Lambda Proxy and API Gateway. Example:
84
+ #
85
+ # "X-Amz-Cf-Id": "W8DF6J-lx1bkV00eCiBwIq5dldTSGGiG4BinJlxvN_4o8fCZtbsVjw==",
86
+ # "X-Amzn-Trace-Id": "Root=1-5a0dc1ac-58a7db712a57d6aa4186c2ac",
87
+ # "X-Forwarded-For": "88.88.88.88, 54.239.203.117",
88
+ # "X-Forwarded-Port": "443",
89
+ # "X-Forwarded-Proto": "https",
90
+ #
91
+ # For sample dump of the event headers, check out:
92
+ # spec/fixtures/samples/event-headers-form-post.json
93
+
94
+ headers
95
+ end
96
+
97
+ def query_string_parameters
98
+ Rack::Utils.parse_nested_query(@env['QUERY_STRING'])
99
+ end
100
+
101
+ # To get the post body:
102
+ # rack.input: #<StringIO:0x007f8ccf8db9a0>
103
+ def get_body
104
+ # @env["rack.input"] is always provided by rack and we should make
105
+ # the test data always have rack.input to mimic rack, but but handling
106
+ # it this way because it's simpler.
107
+ input = @env["rack.input"] || StringIO.new
108
+ body = input.read
109
+ # return nil for blank string, because thats what Lambda AWS_PROXY does
110
+ body unless body.empty?
111
+ end
112
+
113
+ def find_controller_class
114
+ # posts#edit => PostsController
115
+ @route.controller_name.constantize
116
+ end
117
+
118
+ def find_controller_action
119
+ @route.action_name
120
+ end
121
+ end
122
+ end