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,22 @@
1
+ require 'json'
2
+
3
+ # Jets::Lambda::Functions represents a collection of Lambda functions.
4
+ #
5
+ # Jets::Lambda::Functions is the superclass of:
6
+ # Jets::Controller::Base
7
+ # Jets::Job::Base
8
+ module Jets::Lambda
9
+ class Functions
10
+ attr_reader :event, :context, :meth
11
+ def initialize(event, context, meth)
12
+ @event = event # Hash, JSON.parse(event) ran BaseProcessor
13
+ @context = context # Hash. JSON.parse(context) ran in BaseProcessor
14
+ @meth = meth
15
+ # store meth because it is useful to for identifying the which template
16
+ # to use later.
17
+ end
18
+
19
+ include Dsl # At the end so methods like event, context and method
20
+ # do not trigger method_added
21
+ end
22
+ end
@@ -0,0 +1,77 @@
1
+ class Jets::Lambda::Task
2
+ attr_accessor :class_name, :type
3
+ attr_reader :meth, :properties, :lang
4
+ def initialize(class_name, meth, options={})
5
+ @class_name = class_name.to_s # use at EventsRuleMapper#full_task_name
6
+ @meth = meth
7
+ @options = options
8
+ @type = options[:type] || get_type # controller, job, or function
9
+ @properties = options[:properties] || {}
10
+ @lang = options[:lang] || :ruby
11
+ end
12
+
13
+ def name
14
+ @meth
15
+ end
16
+
17
+ @@lang_exts = {
18
+ ruby: '.rb',
19
+ python: '.py',
20
+ node: '.js',
21
+ }
22
+ def lang_ext
23
+ @@lang_exts[@lang]
24
+ end
25
+
26
+ # The get_type method works for controller and job classes.
27
+ #
28
+ # Usually able to get the type from the class name. Examples:
29
+ #
30
+ # PostsController => controller
31
+ # HardJob => job
32
+ #
33
+ # However, for function types, we are not able to get the type for multiple of
34
+ # reasons. First, function types are allowed to be named with or without
35
+ # _function. Examples:
36
+ #
37
+ # path => class => type
38
+ # app/functions/hello.rb => Hello => function
39
+ # app/functions/hello_function.rb => HelloFunction => function
40
+ #
41
+ # The second reason is that functions are not regular ruby classes. Instead they
42
+ # are anonymous classes created with Class.new. When classes are created with
43
+ # Class.new the method_added hook has "" (blank string) as the self class name.
44
+ # We add the class_type to the task later on as we are constructing the class
45
+ # as part of the Class.new logic.
46
+ #
47
+ # For controller and job standard ruby classes though it can easily be
48
+ # determinated as part of initialization. So we get the type for convenience then.
49
+ #
50
+ # For anonymous function classes, we just set to nil and will later fix in
51
+ # FunctionConstructor.
52
+ #
53
+ # Returns: "controller", "job" or nil
54
+ def get_type
55
+ unless @class_name.empty? # when anonymous class is created with Class.new
56
+ @class_name.underscore.split('_').last # controller, job or rule
57
+ end
58
+ end
59
+
60
+ def full_handler(handler_function)
61
+ "#{handler_base}.#{handler_function}"
62
+ end
63
+
64
+ def handler_path
65
+ "#{handler_base}#{lang_ext}"
66
+ end
67
+
68
+ def handler_base
69
+ base = "handlers/#{@type.pluralize}/#{@class_name.underscore}"
70
+ base += "/#{@lang}" if @lang != :ruby
71
+ base += "/#{@meth}"
72
+ end
73
+
74
+ def poly_src_path
75
+ handler_path.sub("handlers/", "app/")
76
+ end
77
+ end
@@ -0,0 +1,61 @@
1
+ # This class groups the naming in one place.
2
+ # Some naming is for CloudFormation
3
+ # Some are for the Build process
4
+ class Jets::Naming
5
+ # Mainly used by build.rb
6
+ class << self
7
+ def template_path(app_class)
8
+ underscored = app_class.to_s.underscore.gsub('/','-')
9
+ "#{template_path_prefix}-#{underscored}.yml"
10
+ end
11
+
12
+ def template_path_prefix
13
+ "#{Jets.build_root}/templates/#{Jets.config.project_namespace}"
14
+ end
15
+
16
+ # consider moving these methods into cfn/builder/helpers.rb or that area.
17
+ def parent_template_path
18
+ "#{template_path_prefix}.yml"
19
+ end
20
+
21
+ # consider moving these methods into cfn/builder/helpers.rb or that area.
22
+ def api_gateway_template_path
23
+ "#{template_path_prefix}-api-gateway.yml"
24
+ end
25
+
26
+ def api_gateway_deployment_template_path
27
+ "#{template_path_prefix}-api-gateway-deployment.yml"
28
+ end
29
+
30
+ def parent_stack_name
31
+ File.basename(parent_template_path, ".yml")
32
+ end
33
+
34
+ def gateway_api_name
35
+ "#{Jets.config.project_namespace}"
36
+ end
37
+
38
+ def code_s3_key
39
+ md5_zipfile = File.basename(md5_code_zipfile)
40
+ "jets/code/#{md5_zipfile}"
41
+ end
42
+
43
+ # build was already ran and that a file that contains the md5 path exists
44
+ # at Jets.build_root/code/current-md5-filename.txt
45
+ #
46
+ # md5_code_zipfile: /tmp/jets/demo/code/code-2e0e18f6.zip
47
+ def md5_code_zipfile
48
+ path = "#{Jets.build_root}/code/current-md5-filename.txt"
49
+ File.exist?(path) ? IO.read(path) : "current-md5-filename-doesnt-exist"
50
+ end
51
+ # The current-md5-filename.txt gets created as a part of CodeBuilder's build
52
+ # process.
53
+ # And is required to be used much later for cfn/ship and base_child_builder
54
+ # They need set an s3_key which requires the md5_zip_dest.
55
+ # It is a pain to pass this all the way up from the
56
+ # CodeBuilder class.
57
+ # We store the "/tmp/jets/demo/code/code-a8a604aa.zip" into a
58
+ # file that can be read from any places where this is needed.
59
+ # Can also just generate a "fake file" for specs
60
+ end
61
+ end
@@ -0,0 +1,30 @@
1
+ class Pascalize
2
+ class << self
3
+ # Specialized pascalize that will not pascalize keys under the
4
+ # Variables part of the hash structure.
5
+ # Based on: https://stackoverflow.com/questions/8706930/converting-nested-hash-keys-from-camelcase-to-snake-case-in-ruby
6
+ def pascalize(value, parent_key=nil)
7
+ case value
8
+ when Array
9
+ value.map { |v| pascalize(v) }
10
+ when Hash
11
+ initializer = value.map do |k, v|
12
+ new_key = pascal_key(k, parent_key)
13
+ [new_key, pascalize(v, new_key)]
14
+ end
15
+ Hash[initializer]
16
+ else
17
+ value
18
+ end
19
+ end
20
+
21
+ def pascal_key(k, parent_key=nil)
22
+ if parent_key == "Variables" # do not pascalize keys anything under Variables
23
+ k
24
+ else
25
+ k = k.to_s.camelize
26
+ k.slice(0,1).capitalize + k.slice(1..-1) # capitalize first letter only
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,61 @@
1
+ module Jets
2
+ class PolyFun
3
+ autoload :LambdaExecutor, 'jets/poly_fun/lambda_executor' # main class delegates to other classes
4
+
5
+ autoload :BaseExecutor, 'jets/poly_fun/base_executor'
6
+ autoload :PythonExecutor, 'jets/poly_fun/python_executor'
7
+ autoload :NodeExecutor, 'jets/poly_fun/node_executor'
8
+
9
+ autoload :PythonError, 'jets/poly_fun/python_error'
10
+ autoload :NodeError, 'jets/poly_fun/node_error'
11
+
12
+ extend Memoist
13
+
14
+ def initialize(app_class, app_meth)
15
+ @app_class = app_class # already a Constant, IE: PostController
16
+ @app_meth = app_meth.to_sym
17
+ end
18
+
19
+ def run(event, context={})
20
+ if task.lang == :ruby
21
+ # controller = PostsController.new(event, content)
22
+ # resp = controller.edit
23
+ @app_class.process(event, context, @app_meth)
24
+ else
25
+ executor = LambdaExecutor.new(task)
26
+ resp = executor.run(event, context)
27
+ if resp["errorMessage"]
28
+ raise_error(resp)
29
+ end
30
+ resp
31
+ end
32
+ end
33
+
34
+ def raise_error(resp)
35
+ backtrace = resp["stackTrace"] + caller
36
+ backtrace = backtrace.map { |l| l.sub(/^\s+/,'') }
37
+ # Adjust the paths from the tmp path to the app path to improve user debugging
38
+ # experience. Example:
39
+ # From:
40
+ # File "/tmp/jets/lite/executor/20180917-16777-43a9e48/app/controllers/jets/public_controller/python/show.py", line 32
41
+ # To:
42
+ # File "app/controllers/jets/public_controller/python/show.py", line 32 backtrace =
43
+ backtrace = backtrace.map do |l|
44
+ if l.include?(Jets.build_root) && !l.include?("lambda_executor.")
45
+ l.sub(/\/tmp\/jets.*executor\/\d{8}-+.*?\//, '')
46
+ else
47
+ l
48
+ end
49
+ end
50
+
51
+ # IE: Jets::PolyFun::PythonError
52
+ error_class = "Jets::PolyFun::#{task.lang.to_s.classify}Error".constantize
53
+ raise error_class.new(resp["errorMessage"], backtrace)
54
+ end
55
+
56
+ def task
57
+ @app_class.all_tasks[@app_meth]
58
+ end
59
+ memoize :task
60
+ end
61
+ end
@@ -0,0 +1,129 @@
1
+ require 'open3'
2
+ require 'tmpdir'
3
+
4
+ class Jets::PolyFun
5
+ class BaseExecutor
6
+ extend Memoist
7
+
8
+ def initialize(task)
9
+ @task = task
10
+ end
11
+
12
+ # Handler is in properties:
13
+ # 1. copy lambda function into tmp folder
14
+ # 2. generate Lang wrapper script
15
+ # 3. call wrapper script from ruby. Handle stdout and stderr and result. Pass info back to ruby
16
+ def run(event, context)
17
+ @temp_dir = create_tmpdir
18
+ copy_src_to_temp
19
+ write(code)
20
+ result = run_lambda_executor(event, context)
21
+ cleanup
22
+ result
23
+ end
24
+
25
+ def write(code)
26
+ puts "lambda_executor_script #{lambda_executor_script}" if ENV['KEEP_LAMBDA_WRAPPER']
27
+ IO.write(lambda_executor_script, code)
28
+ end
29
+
30
+ # Mimic Dir.mktmpdir randomness, not using Dir.mktmpdir because that generates
31
+ # the folder at the /tmp level only.
32
+ def create_tmpdir
33
+ random = "#{Time.now.strftime("%Y%d%H")}-#{Process.pid}-#{SecureRandom.hex[0..6]}"
34
+ tmpdir = "#{Jets.build_root}/executor/#{random}"
35
+ FileUtils.mkdir_p(tmpdir)
36
+ tmpdir
37
+ end
38
+
39
+ def copy_src_to_temp
40
+ app_class = @task.class_name.constantize
41
+ internal = app_class.respond_to?(:internal) && app_class.internal
42
+ src = internal ?
43
+ "#{File.expand_path("../internal", File.dirname(__FILE__))}/#{@task.poly_src_path}" :
44
+ "#{Jets.root}#{@task.poly_src_path}"
45
+ dest = "#{@temp_dir}/#{@task.poly_src_path}"
46
+
47
+ FileUtils.mkdir_p(File.dirname(dest))
48
+ FileUtils.cp(src, dest)
49
+ end
50
+
51
+ def lambda_executor_script
52
+ File.dirname("#{@temp_dir}/#{@task.poly_src_path}") + "/lambda_executor" + @task.lang_ext
53
+ end
54
+
55
+ # When polymorphic method errors, this method reproduces an error in the lambda format
56
+ # Here's some examples to help example:
57
+ #
58
+ # Example of what the raw python prints out to stderr:
59
+ #
60
+ # Traceback (most recent call last):
61
+ # File "/tmp/jets/lite/executor/20180804-10727-mcs6qk/lambda_executor.py", line 6, in <module>
62
+ # resp = handle(event, context)
63
+ # File "/tmp/jets/lite/executor/20180804-10727-mcs6qk/index.py", line 22, in handle
64
+ # return response({'message': e.message}, 400)
65
+ # File "/tmp/jets/lite/executor/20180804-10727-mcs6qk/index.py", line 5, in response
66
+ # badcode
67
+ # NameError: global name 'badcode' is not defined
68
+ #
69
+ # So last line has the error summary info. Other lines have stack trace after the Traceback indicator.
70
+ #
71
+ # Example of the reproduced lambda error format:
72
+ #
73
+ # {
74
+ # "errorMessage": "'NameError' object has no attribute 'message'",
75
+ # "errorType": "AttributeError",
76
+ # "stackTrace": [
77
+ # [
78
+ # "/var/task/handlers/controllers/posts_controller/python/index.py",
79
+ # 22,
80
+ # "handle",
81
+ # "return response({'message': e.message}, 400)"
82
+ # ]
83
+ # ]
84
+ # }
85
+ #
86
+ def run_lambda_executor(event, context)
87
+ interpreter = @task.lang
88
+ command = %Q|#{interpreter} #{lambda_executor_script} '#{JSON.dump(event)}' '#{JSON.dump(context)}'|
89
+ stdout, stderr, status = Open3.capture3(command)
90
+ # puts "=> #{command}".colorize(:green)
91
+ # puts "stdout #{stdout}"
92
+ # puts "stderr #{stderr}"
93
+ # puts "status #{status}"
94
+ if status.success?
95
+ stdout
96
+ else
97
+ # We'll mimic the way lambda displays an error.
98
+ # $stderr.puts(stderr) # uncomment to debug
99
+ error_lines = stderr.split("\n")
100
+ error_message = error_lines.pop
101
+ error_type = error_message.split(':').first
102
+ error_lines.shift # remove first line that has the Traceback
103
+ stack_trace = error_lines.reverse # python shows stack trace in opposite order from ruby
104
+ JSON.dump(
105
+ "errorMessage" => error_message,
106
+ "errorType" => error_type, # hardcode
107
+ "stackTrace" => stack_trace
108
+ )
109
+ end
110
+ end
111
+
112
+ def cleanup
113
+ FileUtils.rm_rf(@temp_dir) unless ENV['KEEP_LAMBDA_WRAPPER']
114
+ end
115
+
116
+ def handler
117
+ # Must use FunctionProperties to get the handler because that the class that combines
118
+ # the mutiple sources of how the handler can get set.
119
+ # puts "handler path #{@task.handler_path}"
120
+ #
121
+ # IE: Jets::Cfn::TemplateBuilders::FunctionProperties::PythonBuilder
122
+ builder_class = "Jets::Cfn::TemplateBuilders::FunctionProperties::#{@task.lang.to_s.classify}Builder".constantize
123
+ builder = builder_class.new(@task)
124
+ full_handler = builder.properties["Handler"] # full handler here
125
+ File.extname(full_handler).sub(/^./,'') # the extension of the full handler is the handler
126
+ end
127
+ memoize :handler
128
+ end
129
+ end
@@ -0,0 +1,16 @@
1
+ require 'json'
2
+
3
+ class Jets::PolyFun
4
+ class LambdaExecutor
5
+ def initialize(task)
6
+ @task = task
7
+ end
8
+
9
+ def run(event, context)
10
+ executor_class = "Jets::PolyFun::#{@task.lang.capitalize}Executor".constantize
11
+ executor = executor_class.new(@task)
12
+ text = executor.run(event, context)
13
+ JSON.load(text)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ class Jets::PolyFun
2
+ class NodeError < StandardError
3
+ def initialize(message, backtrace)
4
+ super(message)
5
+ set_backtrace(backtrace)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,54 @@
1
+ class Jets::PolyFun
2
+ class NodeExecutor < BaseExecutor
3
+ # Code for wrapper script that mimics lambda execution. Wrapper script usage:
4
+ #
5
+ # node WRAPPER_SCRIPT EVENT
6
+ #
7
+ # Example:
8
+ #
9
+ # node /tmp/jets/demo/executor/20180804-12816-imqb9/lambda_executor.js '{}'
10
+ #
11
+ def code
12
+ if async_syntax?
13
+ async_code
14
+ else
15
+ callback_code
16
+ end
17
+ end
18
+
19
+ # https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
20
+ def async_syntax?
21
+ app_path = Jets.root + @task.handler_path.sub('handlers/', 'app/')
22
+ source_code = IO.read(app_path)
23
+ source_code.match(/=\s*async.*\(/)
24
+ end
25
+
26
+ def async_code
27
+ <<-EOL
28
+ var event = process.argv[2]
29
+ event = JSON.parse(event)
30
+ var context = {}
31
+
32
+ var app = require("./#{@task.meth}.js")
33
+ app.#{handler}(event, context).then(resp => console.log(JSON.stringify(resp)))
34
+ EOL
35
+ end
36
+
37
+
38
+ def callback_code
39
+ <<-EOL
40
+ function callback(error, response) {
41
+ var text = JSON.stringify(response)
42
+ console.log(text)
43
+ }
44
+
45
+ var event = process.argv[2]
46
+ event = JSON.parse(event)
47
+ var context = {}
48
+
49
+ var app = require("./#{@task.meth}.js")
50
+ var resp = app.#{handler}(event, context, callback)
51
+ EOL
52
+ end
53
+ end
54
+ end