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