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,151 @@
1
+ require "thor"
2
+
3
+ # Override thor's long_desc identation behavior
4
+ # https://github.com/erikhuda/thor/issues/398
5
+ class Thor
6
+ module Shell
7
+ class Basic
8
+ def print_wrapped(message, options = {})
9
+ message = "\n#{message}" unless message.starts_with?("\n")
10
+ stdout.puts message
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ class Jets::Commands::Base < Thor
17
+ class << self
18
+ # thor_args is an array of commands. Examples:
19
+ # ["help"]
20
+ # ["dynamodb:migrate"]
21
+ #
22
+ # Same signature as RakeCommand.perform. Not using full_command.
23
+ def perform(full_command, thor_args)
24
+ config = {} # doesnt seem like config is used
25
+ dispatch(nil, thor_args, nil, config)
26
+ end
27
+
28
+ # Hacky way to handle error for 'jets new' when no project name is passed in to avoid
29
+ # this error:
30
+ #
31
+ # required arguments 'project_name' (Thor::RequiredArgumentMissingError)
32
+ def dispatch(command, given_args, given_opts, config)
33
+ if given_args.reject{|s| s =~ /^-/} == ['new'] # user forgot to pass a project name
34
+ given_args = ['help', 'new']
35
+ end
36
+ super
37
+ end
38
+
39
+ # Track all command subclasses.
40
+ def subclasses
41
+ @subclasses ||= []
42
+ end
43
+
44
+ def inherited(base)
45
+ super
46
+
47
+ if base.name
48
+ self.subclasses << base
49
+ end
50
+ end
51
+
52
+ # Useful for help menu when we need to have all the definitions loaded.
53
+ # Using constantize instead of require so we dont care about
54
+ # order. The eager load actually uses autoloading.
55
+ def eager_load!
56
+ path = File.expand_path("../../", __FILE__)
57
+ Dir.glob("#{path}/commands/**/*.rb").select do |path|
58
+ next if !File.file?(path) or path =~ /templates/ or path =~ %r{/markdown/}
59
+
60
+ class_name = path
61
+ .sub(/\.rb$/,'')
62
+ .sub(%r{.*/jets/commands}, 'jets/commands')
63
+ .classify
64
+ class_name.sub!(/Task$/, "Tasks") # special rule here for Tasks class
65
+ # NOTE: Weird thing where Jets::Commands::Db::Task => Thor::Command
66
+ # because Task is a class available to Thor I believe.
67
+ puts "eager_load! loading path: #{path} class_name: #{class_name}" if ENV['DEBUG']
68
+ class_name.constantize # dont have to worry about order.
69
+ end
70
+ end
71
+
72
+ # Fully qualifed task names. Examples:
73
+ # build
74
+ # process:controller
75
+ # dynamodb:migrate:down
76
+ def namespaced_commands
77
+ eager_load!
78
+ subclasses.map do |klass|
79
+ klass.all_tasks.keys.map do |task_name|
80
+ klass = klass.to_s.sub('Jets::Commands::','')
81
+ namespace = klass =~ /^Main/ ? nil : klass.underscore.gsub('/',':')
82
+ [namespace, task_name].compact.join(':')
83
+ end
84
+ end.flatten.sort
85
+ end
86
+
87
+ # Use Jets banner instead of Thor to account for namespaces in commands.
88
+ def banner(command, namespace = nil, subcommand = false)
89
+ namespace = namespace_from_class(self)
90
+ command_name = command.usage # set with desc when defining tht Thor class
91
+ namespaced_command = [namespace, command_name].compact.join(':')
92
+
93
+ "jets #{namespaced_command}"
94
+ end
95
+
96
+ def namespace_from_class(klass)
97
+ namespace = klass.to_s.sub('Jets::Commands::', '').underscore.gsub('/',':')
98
+ namespace unless namespace == "main"
99
+ end
100
+
101
+ def help_list(all=false)
102
+ # hack to show hidden comands when requested
103
+ Thor::HiddenCommand.class_eval do
104
+ def hidden?; false; end
105
+ end if all
106
+
107
+ list = []
108
+ eager_load!
109
+ subclasses.each do |klass|
110
+ commands = klass.printable_commands(true, false)
111
+ commands.reject! { |array| array[0].include?(':help') }
112
+ list += commands
113
+ end
114
+
115
+ list.sort_by! { |array| array[0] }
116
+ end
117
+
118
+ def klass_from_namespace(namespace)
119
+ if namespace.nil?
120
+ Jets::Commands::Main
121
+ else
122
+ class_name = namespace.gsub(':','/')
123
+ class_name = "Jets::Commands::#{class_name.classify}"
124
+ class_name.constantize
125
+ end
126
+ end
127
+
128
+ # If this fails to match then it'l just return the original full command
129
+ def autocomplete(full_command)
130
+ return nil if full_command.nil? # jets help
131
+
132
+ eager_load!
133
+
134
+ words = full_command.split(':')
135
+ namespace = words[0..-2].join(':') if words.size > 1
136
+ command = words.last
137
+
138
+ # Thor's normalize_command_name autocompletes the command but then we need to add the namespace back
139
+ begin
140
+ thor_subclass = klass_from_namespace(namespace) # could NameError
141
+ command = thor_subclass.normalize_command_name(command) # could Thor::AmbiguousCommandError
142
+ [namespace, command].compact.join(':')
143
+ rescue NameError
144
+ full_command # return original full_command
145
+ rescue Thor::AmbiguousCommandError => e
146
+ puts "Unable to autodetect the command name. #{e.message}."
147
+ full_command # return original full_command
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,186 @@
1
+ require 'digest'
2
+
3
+ module Jets::Commands
4
+ class Build
5
+ include Jets::Timing
6
+ include StackInfo
7
+
8
+ def initialize(options)
9
+ @options = options.dup
10
+ end
11
+
12
+ def run
13
+ puts "Building project for Lambda..."
14
+ return if @options[:noop]
15
+ # run gets called from the CLI and does not have all the stack_options yet.
16
+ # We compute it and change the options early here.
17
+ @options.merge!(stack_type: stack_type, s3_bucket: s3_bucket)
18
+ build
19
+ end
20
+ time :run
21
+
22
+ def build
23
+ build_code unless @options[:templates_only]
24
+ build_templates
25
+ end
26
+ time :build
27
+
28
+ def build_code
29
+ Jets::Builders::CodeBuilder.new.build unless @options[:noop]
30
+ end
31
+ time :build_code
32
+
33
+ def build_templates
34
+ if @options[:stack_type] == :minimal
35
+ build_minimal_template
36
+ else
37
+ build_all_templates
38
+ end
39
+ end
40
+ time :build_templates
41
+
42
+ def build_all_templates
43
+ clean_templates
44
+ # TODO: move this build.rb logic to cfn/builder.rb
45
+ ## CloudFormation templates
46
+ puts "Building Lambda functions as CloudFormation templates."
47
+ # 1. Shared templates - child templates needs them
48
+ build_api_gateway_templates
49
+ # 2. Child templates - parent template needs them
50
+ build_child_templates
51
+ # 3. Finally parent template
52
+ build_parent_template # must be called at the end
53
+ end
54
+
55
+ def build_minimal_template
56
+ parent = Jets::Cfn::TemplateBuilders::ParentBuilder.new(@options)
57
+ parent.build
58
+ end
59
+
60
+ def build_api_gateway_templates
61
+ gateway = Jets::Cfn::TemplateBuilders::ApiGatewayBuilder.new(@options)
62
+ gateway.build
63
+ deployment = Jets::Cfn::TemplateBuilders::ApiGatewayDeploymentBuilder.new(@options)
64
+ deployment.build
65
+ end
66
+
67
+ def build_child_templates
68
+ app_files.each do |path|
69
+ build_child_template(path)
70
+ end
71
+ end
72
+
73
+ # path: app/controllers/comments_controller.rb
74
+ # path: app/jobs/easy_job.rb
75
+ def build_child_template(path)
76
+ class_path = path.sub(%r{.*app/\w+/},'').sub(/\.rb$/,'')
77
+ class_name = class_path.classify
78
+ class_name.constantize # load app/**/* class definition
79
+
80
+ md = path.match(%r{app/(.*?)/}) # extract: controller, job or function
81
+ process_class = md[1].classify
82
+ builder_class = "Jets::Cfn::TemplateBuilders::#{process_class}Builder".constantize
83
+
84
+ # Examples:
85
+ # Jets::Cfn::TemplateBuilders::JobBuilder.new(EasyJob)
86
+ # Jets::Cfn::TemplateBuilders::ControllerBuilder.new(PostsController)
87
+ # Jets::Cfn::TemplateBuilders::FunctionBuilder.new(Hello)
88
+ # Jets::Cfn::TemplateBuilders::FunctionBuilder.new(HelloFunction)
89
+ app_klass = Jets::Klass.from_path(path)
90
+ builder = builder_class.new(app_klass)
91
+ builder.build
92
+ end
93
+
94
+ def build_parent_template
95
+ parent = Jets::Cfn::TemplateBuilders::ParentBuilder.new(@options)
96
+ parent.build
97
+ end
98
+
99
+ def clean_templates
100
+ FileUtils.rm_rf("#{Jets.build_root}/templates")
101
+ end
102
+
103
+ def app_files
104
+ self.class.app_files
105
+ end
106
+
107
+ # Crucial that the Dir.pwd is in the tmp_app_root because for
108
+ # because Jets.boot set ups autoload_paths and this is how project
109
+ # classes are loaded.
110
+ # TODO: rework code so this is not the case.
111
+ def self.app_files
112
+ paths = []
113
+ expression = "#{Jets.root}app/**/**/*.rb"
114
+ Dir.glob(expression).each do |path|
115
+ return false unless File.file?(path)
116
+ next unless app_file?(path)
117
+
118
+ relative_path = path.sub(Jets.root.to_s, '')
119
+ # Rids of the Jets.root at beginning
120
+ paths << relative_path
121
+ end
122
+ paths += internal_app_files
123
+ paths
124
+ end
125
+
126
+ def self.poly_only?
127
+ # Scans all the app code and look for any methods that are ruby.
128
+ # If any method is written in ruby then we know the app is not a
129
+ # soley polymorphic non-ruby app.
130
+ has_ruby = app_files.detect do |path|
131
+ # 1. remove app/controllers or app/jobs, etc
132
+ # 2. remove .rb extension
133
+ app_file = path.sub(%r{app/\w+/},'').sub(/\.rb$/,'')
134
+ # Internal jets controllers like Welcome and Public need a different regexp
135
+ app_file = app_file.sub(%r{.*lib/jets/internal/},'')
136
+ app_klass = app_file.classify.constantize # IE: PostsController, Jets::PublicController
137
+ langs = app_klass.tasks.map(&:lang)
138
+ langs.include?(:ruby)
139
+ end
140
+ !has_ruby
141
+ end
142
+
143
+ # Add internal Jets controllers if they are being used
144
+ def self.internal_app_files
145
+ paths = []
146
+ controllers = File.expand_path("../../internal/app/controllers/jets", __FILE__)
147
+
148
+ welcome = Jets::Router.has_controller?("Jets::WelcomeController")
149
+ paths << "#{controllers}/public_controller.rb" if welcome
150
+
151
+ public_catchall = Jets::Router.has_controller?("Jets::PublicController")
152
+ paths << "#{controllers}/welcome_controller.rb" if public_catchall
153
+
154
+ jobs = File.expand_path("../../internal/app/jobs/jets", __FILE__)
155
+ paths << "#{jobs}/preheat_job.rb"
156
+
157
+ paths
158
+ end
159
+
160
+ def self.app_file?(path)
161
+ return false unless File.extname(path) == ".rb"
162
+ # Do not define lamda functions for the application_controller.rb or
163
+ # application_job.rb
164
+ excludes = %w[
165
+ application_controller.rb
166
+ application_job.rb
167
+ ]
168
+ return false if excludes.detect { |p| path.include?(p) }
169
+
170
+ includes = %w[
171
+ app/controllers
172
+ app/jobs
173
+ app/functions
174
+ app/rules
175
+ ]
176
+ return true if includes.detect { |p| path.include?(p) }
177
+
178
+ false
179
+ end
180
+
181
+ def self.tmp_app_root(full_build_path=false)
182
+ full_build_path ? "#{Jets.build_root}/app_root" : "app_root"
183
+ end
184
+
185
+ end
186
+ end
@@ -0,0 +1,175 @@
1
+ require "base64"
2
+ require "json"
3
+ require "active_support/core_ext/string"
4
+
5
+ class Jets::Commands::Call
6
+ autoload :BaseGuesser, "jets/commands/call/base_guesser"
7
+ autoload :AutoloadGuesser, "jets/commands/call/autoload_guesser"
8
+ autoload :AnonymousGuesser, "jets/commands/call/anonymous_guesser"
9
+ autoload :Guesser, "jets/commands/call/guesser"
10
+
11
+ include Jets::AwsServices
12
+
13
+ def initialize(provided_function_name, event, options={})
14
+ @options = options
15
+ @guess = @options[:guess].nil? ? true : @options[:guess]
16
+
17
+ @provided_function_name = provided_function_name
18
+ @event = event
19
+
20
+ @invocation_type = options[:invocation_type] || "RequestResponse"
21
+ @log_type = options[:log_type] || "Tail"
22
+ @qualifier = @qualifier
23
+ end
24
+
25
+ def function_name
26
+ if @guess
27
+ ensure_guesses_found! # possibly exits here
28
+ guesser.function_name # guesser adds namespace already
29
+ else
30
+ [Jets.config.project_namespace, @provided_function_name].join('-')
31
+ end
32
+ end
33
+
34
+ def run
35
+ @options[:local] ? local_run : remote_run
36
+ end
37
+
38
+ # With local mode there is no way to bypass the guesser
39
+ def local_run
40
+ puts "Local mode enabled!"
41
+ ensure_guesses_found! # possibly exits here
42
+ klass = guesser.class_name.constantize
43
+ # Example:
44
+ # PostsController.process(event, context, meth)
45
+ event = JSON.load(transformed_event) || {} # transformed_event is JSON text String
46
+
47
+ fun = Jets::PolyFun.new(klass, guesser.method_name)
48
+ result = fun.run(event) # check the logs for polymorphic function errors
49
+ # Note: even though data might not always be json, the JSON.dump does a
50
+ # good job of not bombing, so always calling it to simplify code.
51
+
52
+ text = Jets::Util.normalize_result(result)
53
+ STDOUT.puts text
54
+ end
55
+
56
+ def remote_run
57
+ puts "Calling lambda function #{function_name} on AWS" unless @options[:mute]
58
+ return if @options[:noop]
59
+
60
+ options = {
61
+ # client_context: client_context,
62
+ function_name: function_name,
63
+ invocation_type: @invocation_type, # "Event", # RequestResponse
64
+ log_type: @log_type, # pretty sweet
65
+ payload: transformed_event, # "fileb://file-path/input.json", <= JSON
66
+ qualifier: @qualifier, # "1",
67
+ }
68
+ begin
69
+ resp = lambda.invoke(options)
70
+ rescue Aws::Lambda::Errors::ResourceNotFoundException
71
+ puts "The function #{function_name} was not found. Maybe check the spelling?".colorize(:red)
72
+ exit
73
+ end
74
+
75
+ if @options[:show_log]
76
+ puts "Last 4KB of log in the x-amz-log-result header:".colorize(:green)
77
+ puts Base64.decode64(resp.log_result)
78
+ end
79
+
80
+ add_console_link_to_clipboard
81
+ result = resp.payload.read # already been normalized/JSON.dump by AWS
82
+ unless @options[:mute_output]
83
+ STDOUT.puts result # only thing that goes to stdout
84
+ end
85
+ end
86
+
87
+ def guesser
88
+ @guesser ||= Guesser.new(@provided_function_name)
89
+ end
90
+
91
+ def ensure_guesses_found!
92
+ unless guesser.class_name and guesser.method_name
93
+ puts guesser.error_message
94
+ exit
95
+ end
96
+ end
97
+
98
+ # @event is String because it can be the file:// notation
99
+ # Returns text String for the lambda.invoke payload.
100
+ def transformed_event
101
+ text = @event
102
+ if text && text.include?("file://")
103
+ text = load_event_from_file(text)
104
+ end
105
+
106
+ check_valid_json!(text)
107
+
108
+ puts "Function name: #{function_name.colorize(:green)}" unless @options[:mute]
109
+ return text unless function_name.include?("_controller-")
110
+ return text if @options[:lambda_proxy] == false
111
+
112
+ event = JSON.load(text)
113
+ lambda_proxy = {"queryStringParameters" => event}
114
+ JSON.dump(lambda_proxy)
115
+ end
116
+
117
+ def load_event_from_file(text)
118
+ path = text.gsub('file://','')
119
+ path = "#{Jets.root}#{path}" unless path[0..0] == '/'
120
+ unless File.exist?(path)
121
+ puts "File #{path} does not exist. Are you sure the file exists?".colorize(:red)
122
+ exit
123
+ end
124
+ text = IO.read(path)
125
+ end
126
+
127
+ # Exits with friendly error message when user provides bad just
128
+ def check_valid_json!(text)
129
+ JSON.load(text)
130
+ rescue JSON::ParserError => e
131
+ puts "Invalid json provided:\n '#{text}'"
132
+ puts "Exiting... Please try again and provide valid json."
133
+ exit 1
134
+ end
135
+
136
+ # So use can quickly paste this into their browser if they want to see the function
137
+ # via the Lambda console
138
+ def add_console_link_to_clipboard
139
+ return unless RUBY_PLATFORM =~ /darwin/
140
+ return unless system("type pbcopy > /dev/null")
141
+
142
+ # TODO: for add_console_link_to_clipboard get the region from the ~/.aws/config and AWS_PROFILE setting
143
+ region = Aws.config[:region] || 'us-east-1'
144
+ link = "https://console.aws.amazon.com/lambda/homepage?region=#{region}#/functions/#{function_name}?tab=configuration"
145
+ system("echo #{link} | pbcopy")
146
+ puts "Pro tip: The Lambda Console Link to the #{function_name} function has been added to your clipboard." unless @options[:mute]
147
+ end
148
+
149
+ # Client context must be a valid Base64-encoded JSON object
150
+ # Example: http://docs.aws.amazon.com/mobileanalytics/latest/ug/PutEvents.html
151
+ # TODO: figure out how to sign client_context
152
+ def client_context
153
+ context = {
154
+ "client" => {
155
+ "client_id" => "Jets",
156
+ "app_title" => "jets call cli",
157
+ "app_version_name" => Jets::VERSION,
158
+ },
159
+ "custom" => {},
160
+ "env" =>{
161
+ "platform" => RUBY_PLATFORM,
162
+ "platform_version" => RUBY_VERSION,
163
+ }
164
+ }
165
+ Base64.encode64(JSON.dump(context))
166
+ end
167
+
168
+ # For this class redirect puts to stderr so user can pipe output to tools like
169
+ # jq. Example:
170
+ # jets call posts_controller-index '{"test":1}' | jq .
171
+ def puts(text)
172
+ $stderr.puts(text)
173
+ end
174
+
175
+ end