jets 0.2.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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,154 @@
1
+ # def extract_gems
2
+ # headline "Replacing compiled gems with Lambda Linux versions."
3
+ # Lambdagem::Extract::Gem.new(JETS_RUBY_VERSION,
4
+ # s3: "lambdagems",
5
+ # dest: full(cache_area),
6
+ # ).run
7
+ # end
8
+ class Jets::Builders
9
+ class GemReplacer
10
+ extend Memoist
11
+ attr_reader :missing_gems
12
+ def initialize(ruby_version, options)
13
+ @ruby_version = ruby_version
14
+ @options = options
15
+ @missing_gems = [] # keeps track of gems that are not found in any of the lambdagems sources
16
+ end
17
+
18
+ def run
19
+ # Checks whether the gem is found on at least one of the lambdagems sources.
20
+ # By the time the loop finishes, found_gems will hold a map of gem names to found
21
+ # url sources. Example:
22
+ #
23
+ # found_gems = {
24
+ # "nokogiri-1.8.4" => "https://lambdagems.com",
25
+ # "pg-0.21.0" => "https://anothersource.com",
26
+ # }
27
+ #
28
+ found_gems = {}
29
+ compiled_gems.each do |gem_name|
30
+ gem_exists = false
31
+ Jets.config.lambdagems.sources.each do |source|
32
+ exist = Lambdagem::Exist.new(lambdagems_url: source)
33
+ found = exist.check(gem_name)
34
+ # gem exists on at least of the lambdagem sources
35
+ if found
36
+ gem_exists = true
37
+ found_gems[gem_name] = source
38
+ break
39
+ end
40
+ end
41
+ unless gem_exists
42
+ @missing_gems << gem_name
43
+ end
44
+ end
45
+
46
+ # Exits early if not all the linux gems are available.
47
+ # It better to error now than deploy a broken package to AWS Lambda.
48
+ # Provide users with message about using their own lambdagems source.
49
+ unless @missing_gems.empty?
50
+ puts missing_gems_message
51
+ exit 1
52
+ end
53
+
54
+ # Reaching here means we can download and extract the gems
55
+ found_gems.each do |gem_name, source|
56
+ gem_extractor = Lambdagem::Extract::Gem.new(gem_name, @options.merge(lambdagems_url: source))
57
+ gem_extractor.run
58
+ end
59
+
60
+ tidy
61
+ end
62
+
63
+ def missing_gems_message
64
+ template = <<-EOL
65
+ Your project requires compiled gems were not available in any of your lambdagems sources. Unavailable pre-compiled gems:
66
+ <% missing_gems.each do |gem| %>
67
+ * <%= gem -%>
68
+ <% end %>
69
+
70
+ Your current lambdagems sources:
71
+ <% Jets.config.lambdagems.sources.map do |source| %>
72
+ * <%= source -%>
73
+ <% end %>
74
+
75
+ Jets is unable to build a deployment package that will work on AWS Lambda without the required pre-compiled gems. To remedy this, you can:
76
+
77
+ * Build the gem yourself and add it to your own custom lambdagems sources. Refer to the Lambda Gems Docs: http://rubyonjets.com/docs/lambdagems
78
+ * Wait until it added to lambdagems.com. No need to report this to us, as we've already been notified.
79
+ * Use another gem that does not require compilation.
80
+
81
+ Compiled gems usually take some time to figure out how to build as they each depend on different libraries and packages. We make an effort add new gems as soon as we can. You can support us by going to: http://rubyonjets.com/support-jets/
82
+ EOL
83
+ erb = ERB.new(template, nil, '-') # trim mode https://stackoverflow.com/questions/4632879/erb-template-removing-the-trailing-line
84
+ erb.result(binding)
85
+ end
86
+
87
+ # remove unnecessary files to reduce package size
88
+ def tidy
89
+ tidy_gems("#{@options[:project_root]}/bundled/gems/ruby/*/gems/*")
90
+ tidy_gems("#{@options[:project_root]}/bundled/gems/ruby/*/bundler/gems/*")
91
+ end
92
+
93
+ def tidy_gems(gems_path)
94
+ Dir.glob(gems_path).each do |gem_path|
95
+ tidy_gem(gem_path)
96
+ end
97
+ end
98
+
99
+ # Clean up some unneeded files to try to keep the package size down
100
+ # In a generated jets app this made a decent 9% difference:
101
+ # 175M test2
102
+ # 191M test3
103
+ def tidy_gem(path)
104
+ # remove top level tests and cache folders
105
+ Dir.glob("#{path}/*").each do |path|
106
+ next unless File.directory?(path)
107
+ folder = File.basename(path)
108
+ if %w[test tests spec features benchmark cache doc].include?(folder)
109
+ FileUtils.rm_rf(path)
110
+ end
111
+ end
112
+
113
+ Dir.glob("#{path}/**/*").each do |path|
114
+ next unless File.file?(path)
115
+ ext = File.extname(path)
116
+ if %w[.rdoc .md .markdown].include?(ext) or
117
+ path =~ /LICENSE|CHANGELOG|README/
118
+ FileUtils.rm_f(path)
119
+ end
120
+ end
121
+ end
122
+
123
+ # If there are subfolders compiled_gem_paths might have files deeper
124
+ # in the directory tree. So lets grab the gem name and figure out the
125
+ # unique paths of the compiled gems from there.
126
+ def compiled_gems
127
+ compiled_gem_paths.map { |p| gem_name_from_path(p) }.uniq# + ["whatever-0.0.1"]
128
+ end
129
+ memoize :compiled_gems
130
+
131
+ # Use pre-compiled gem because the gem could have development header shared
132
+ # object file dependencies. The shared dependencies are packaged up as part
133
+ # of the pre-compiled gem so it is available in the Lambda execution environment.
134
+ #
135
+ # Example paths:
136
+ # Macosx:
137
+ # bundled/gems/ruby/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/nokogiri-1.8.1
138
+ # bundled/gems/ruby/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/byebug-9.1.0
139
+ # Official AWS Lambda Linux AMI:
140
+ # bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0-static/nokogiri-1.8.1
141
+ # Circleci Ubuntu based Linux:
142
+ # bundled/gems/ruby/2.5.0/extensions/x86_64-linux/2.5.0/pg-0.21.0
143
+ def compiled_gem_paths
144
+ Dir.glob("#{Jets.build_root}/cache/bundled/gems/ruby/*/extensions/**/**/*.{so,bundle}")
145
+ end
146
+
147
+ # Input: bundled/gems/ruby/2.5.0/extensions/x86_64-darwin-16/2.5.0-static/byebug-9.1.0
148
+ # Output: byebug-9.1.0
149
+ def gem_name_from_path(path)
150
+ regexp = /gems\/ruby\/\d+\.\d+\.\d+\/extensions\/.*?\/.*?\/(.*?)\//
151
+ gem_name = path.match(regexp)[1]
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,76 @@
1
+ require "fileutils"
2
+ require "erb"
3
+
4
+ # Example:
5
+ #
6
+ # Jets::Builders::HandlerGenerator.new(
7
+ # "PostsController",
8
+ # :create, :update
9
+ # )
10
+ class Jets::Builders
11
+ class HandlerGenerator
12
+ def initialize(path)
13
+ @path = path
14
+ end
15
+
16
+ def generate
17
+ poly_shims
18
+ ruby_node_shim
19
+ end
20
+
21
+ def poly_shims
22
+ missing = []
23
+
24
+ deducer = Jets::Builders::Deducer.new(@path)
25
+ poly_tasks = deducer.klass.tasks.select { |t| t.lang != :ruby }
26
+ poly_tasks.each do |task|
27
+ source_path = get_source_path(@path, task)
28
+ if File.exist?(source_path)
29
+ native_function(@path, task)
30
+ else
31
+ missing << source_path
32
+ end
33
+ end
34
+
35
+ unless missing.empty?
36
+ puts "ERROR: Missing source files. Please make sure these source files exist or remove their declarations".colorize(:red)
37
+ puts missing
38
+ exit 1
39
+ end
40
+ end
41
+
42
+ def get_source_path(original_path, task)
43
+ folder = original_path.sub(/\.rb$/,'')
44
+ lang_folder = "#{folder}/#{task.lang}"
45
+ root = Jets.root unless original_path.include?("lib/jets/internal")
46
+ "#{root}#{lang_folder}/#{task.meth}#{task.lang_ext}"
47
+ end
48
+
49
+ # Builds and copies over the native source code: python or node
50
+ def native_function(original_path, task)
51
+ source_path = get_source_path(original_path, task)
52
+ # Handler: handlers/controllers/posts_controller.handle
53
+ dest_path = "#{tmp_app_root}/#{task.handler_path}"
54
+ FileUtils.mkdir_p(File.dirname(dest_path))
55
+ FileUtils.cp(source_path, dest_path)
56
+ end
57
+
58
+ # Generates one big node shim for a entire controller.
59
+ def ruby_node_shim
60
+ deducer = Jets::Builders::Deducer.new(@path)
61
+
62
+ js_path = "#{tmp_app_root}/#{deducer.js_path}"
63
+ FileUtils.mkdir_p(File.dirname(js_path))
64
+
65
+ template_path = File.expand_path('../node-shim.js', __FILE__)
66
+ result = Jets::Erb.result(template_path, deducer: deducer)
67
+
68
+ IO.write(js_path, result)
69
+ end
70
+
71
+ # TODO: move CodeBuilder.tmp_app_root to a common level for HandlerGenerator and CodeBuilder
72
+ def tmp_app_root
73
+ "#{Jets.build_root}/#{CodeBuilder.tmp_app_root}"
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,73 @@
1
+ 'use strict';
2
+ console.log('Loading hello world function');
3
+
4
+ // https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html
5
+
6
+ exports.handler = function(event, context, callback) {
7
+ let name = "you";
8
+ let city = 'World';
9
+ let time = 'day';
10
+ let day = '';
11
+ let responseCode = 200;
12
+ console.log("request: " + JSON.stringify(event));
13
+
14
+ // This is a simple illustration of app-specific logic to return the response.
15
+ // Although only 'event.queryStringParameters' are used here, other request data,
16
+ // such as 'event.headers', 'event.pathParameters', 'event.body', 'event.stageVariables',
17
+ // and 'event.requestContext' can be used to determine what response to return.
18
+ //
19
+ if (event.queryStringParameters !== null && event.queryStringParameters !== undefined) {
20
+ if (event.queryStringParameters.name !== undefined &&
21
+ event.queryStringParameters.name !== null &&
22
+ event.queryStringParameters.name !== "") {
23
+ console.log("Received name: " + event.queryStringParameters.name);
24
+ name = event.queryStringParameters.name;
25
+ }
26
+ }
27
+
28
+ if (event.pathParameters !== null && event.pathParameters !== undefined) {
29
+ if (event.pathParameters.proxy !== undefined &&
30
+ event.pathParameters.proxy !== null &&
31
+ event.pathParameters.proxy !== "") {
32
+ console.log("Received proxy: " + event.pathParameters.proxy);
33
+ city = event.pathParameters.proxy;
34
+ }
35
+ }
36
+
37
+ if (event.headers !== null && event.headers !== undefined) {
38
+ if (event.headers['day'] !== undefined && event.headers['day'] !== null && event.headers['day'] !== "") {
39
+ console.log("Received day: " + event.headers.day);
40
+ day = event.headers.day;
41
+ }
42
+ }
43
+
44
+ if (event.body !== null && event.body !== undefined) {
45
+ let body = JSON.parse(event.body)
46
+ if (body.time)
47
+ time = body.time;
48
+ }
49
+
50
+ let greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. ';
51
+ if (day) greeting += 'Happy ' + day + '!';
52
+
53
+ var responseBody = {
54
+ message: greeting,
55
+ input: event
56
+ };
57
+
58
+ // The output from a Lambda proxy integration must be
59
+ // of the following JSON object. The 'headers' property
60
+ // is for custom response headers in addition to standard
61
+ // ones. The 'body' property must be a JSON string. For
62
+ // base64-encoded payload, you must also set the 'isBase64Encoded'
63
+ // property to 'true'.
64
+ var response = {
65
+ statusCode: responseCode,
66
+ headers: {
67
+ "x-custom-header" : "my custom header value"
68
+ },
69
+ body: JSON.stringify(responseBody)
70
+ };
71
+ console.log("response: " + JSON.stringify(response))
72
+ callback(null, response);
73
+ };
@@ -0,0 +1,151 @@
1
+ 'use strict';
2
+
3
+ const spawn = require('child_process').spawn;
4
+ const fs = require('fs');
5
+ const TMP_LOG_PATH = '/tmp/shim-subprocess.log';
6
+ const subprocess_out = fs.openSync(TMP_LOG_PATH, 'a');
7
+ const subprocess_err = fs.openSync(TMP_LOG_PATH, 'a');
8
+
9
+ function once() {
10
+ // Uncomment fake run once locally. No need to do this on real lambda environment.
11
+ // var filename = '/tmp/once.txt';
12
+ // if (fs.existsSync(filename)) {
13
+ // return;
14
+ // }
15
+ // fs.closeSync(fs.openSync(filename, 'w'));
16
+
17
+ // start tcp server and detach
18
+ const subprocess = spawn('bin/ruby_server', {
19
+ detached: true,
20
+ stdio: [ 'ignore', subprocess_out, subprocess_err ]
21
+ });
22
+ subprocess.on('error', function(err) {
23
+ log('bin/ruby_server error', err);
24
+ });
25
+
26
+ subprocess.on('close', function(exit_code) {
27
+ log("Subprocess was shut down or deattached!");
28
+ });
29
+
30
+ // prevent the parent from waiting for a subprocess to exit
31
+ // https://nodejs.org/api/child_process.html
32
+ subprocess.unref();
33
+ }
34
+
35
+ once();
36
+
37
+ // Produces an Error object that displays in the AWS Lambda test console nicely.
38
+ // The backtrace are the ruby lines, not the nodejs shim error lines.
39
+ // The json payload in the Lambda console looks something like this:
40
+ //
41
+ // {
42
+ // "errorMessage": "RubyError: RuntimeError: error in submethod",
43
+ // "errorType": "RubyError",
44
+ // "stackTrace": [
45
+ // [
46
+ // "line1",
47
+ // "line2",
48
+ // "line3"
49
+ // ]
50
+ // ]
51
+ // }
52
+ //
53
+ function rubyError(resp) {
54
+ var name = resp["errorType"]
55
+ var message = resp["errorMessage"]
56
+ var lines = resp["stackTrace"]
57
+
58
+ var error = new Error(message)
59
+ error.name = name
60
+ error.stack = lines.join("\n")
61
+ return error
62
+ }
63
+
64
+ // On AWS Lambda, we can log to either stdout or stderr and we're okay.
65
+ // But locally when we're testing the shim, the log output can mess up piping
66
+ // to jq. So not logging to stdout because when testing this shim locally the
67
+ // stdout output messes up a pipe to jq.
68
+ function log(text) {
69
+ console.error(text);
70
+ }
71
+
72
+ ////////////////////////////
73
+ // main logic for handler
74
+ const net = require('net');
75
+ const PORT = 8080;
76
+ const HOST = '127.0.0.1';
77
+
78
+ function request(event, handler, callback) {
79
+ log("event:");
80
+ log(event);
81
+ var client = new net.Socket();
82
+ client.connect(PORT, HOST, function() {
83
+ log('Connected to socket');
84
+ client.write(JSON.stringify(event));
85
+ client.write("\r\n") // important: \r\n is how server knows input is done
86
+ client.write(handler);
87
+ client.write("\r\n") // important: \r\n is how server knows input is done
88
+ });
89
+
90
+ // string concatation in javascript is faster than array concatation
91
+ // http://bit.ly/2gBMDs6
92
+ var stdout_buffer = ""; // stdout buffer
93
+ client.on('data', function(buffer) {
94
+ log('Received data from socket: ' + buffer);
95
+ stdout_buffer += buffer;
96
+ });
97
+
98
+ client.on('close', function() {
99
+ log('Socket connection closed');
100
+ // If server is not yet running, socket immediately closes and stdout_buffer
101
+ // is still empty. Return right away for this case, so request can retry.
102
+ if (stdout_buffer == "") {
103
+ return;
104
+ }
105
+
106
+ var resp = JSON.parse(stdout_buffer);
107
+ if (resp["errorMessage"]) {
108
+ // Customize error object for lambda format
109
+ var error = rubyError(resp)
110
+ callback(error);
111
+ } else {
112
+ callback(null, resp);
113
+ }
114
+ client.destroy(); // kill client after server's response
115
+ });
116
+
117
+ client.on('error', function(error) {
118
+ log("Socket error %o", error);
119
+ log("Retrying request");
120
+ setTimeout(function() {
121
+ if (fs.existsSync(TMP_LOG_PATH)) {
122
+ var contents = fs.readFileSync(TMP_LOG_PATH, 'utf8');
123
+ log("subprocess output:");
124
+ log(contents);
125
+ }
126
+ request(event, handler, callback);
127
+ }, 500);
128
+ });
129
+ };
130
+
131
+ <% @deducer.functions.each do |function_name| %>
132
+ exports.<%= function_name %> = (event, context, callback) => {
133
+ request(event, "<%= @deducer.handler_for(function_name) %>", callback);
134
+ }
135
+ <% end %>
136
+
137
+ // for local testing
138
+ if (require.main === module) {
139
+ // fake event and context
140
+ var event = {"hello": "world"}
141
+ // var event = {"body": {"hello": "world"}} // API Gateway wrapper structure
142
+ var context = {"fake": "context"}
143
+ exports.<%= @deducer.functions.first %>(event, context, (error, message) => {
144
+ log("\nLOCAL TESTING OUTPUT")
145
+ if (error) {
146
+ console.log("error message: %o", error)
147
+ } else {
148
+ console.log(JSON.stringify(message)) // stringify
149
+ }
150
+ })
151
+ }