jets 0.8.0 → 0.8.1

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile.lock +3 -1
  4. data/jets.gemspec +2 -0
  5. data/lib/jets/application.rb +1 -1
  6. data/lib/jets/cfn.rb +1 -2
  7. data/lib/jets/cfn/builders.rb +19 -0
  8. data/lib/jets/cfn/builders/api_deployment_builder.rb +32 -0
  9. data/lib/jets/cfn/{template_builders → builders}/api_gateway_builder.rb +10 -21
  10. data/lib/jets/cfn/builders/base_child_builder.rb +49 -0
  11. data/lib/jets/cfn/{template_builders → builders}/controller_builder.rb +7 -7
  12. data/lib/jets/cfn/{template_builders → builders}/function_builder.rb +1 -2
  13. data/lib/jets/cfn/builders/interface.rb +128 -0
  14. data/lib/jets/cfn/{template_builders → builders}/job_builder.rb +2 -2
  15. data/lib/jets/cfn/builders/parent_builder.rb +84 -0
  16. data/lib/jets/cfn/{template_builders → builders}/rule_builder.rb +4 -5
  17. data/lib/jets/commands/base.rb +1 -1
  18. data/lib/jets/commands/build.rb +11 -15
  19. data/lib/jets/commands/delete.rb +12 -0
  20. data/lib/jets/commands/templates/skeleton/Gemfile.tt +1 -0
  21. data/lib/jets/commands/templates/skeleton/config/application.rb.tt +1 -1
  22. data/lib/jets/commands/url.rb +10 -12
  23. data/lib/jets/controller/base.rb +2 -2
  24. data/lib/jets/core.rb +1 -1
  25. data/lib/jets/core_ext/kernel.rb +11 -1
  26. data/lib/jets/internal/app/controllers/jets/public_controller.rb +11 -8
  27. data/lib/jets/lambda/dsl.rb +1 -1
  28. data/lib/jets/lambda/task.rb +9 -1
  29. data/lib/jets/naming.rb +2 -2
  30. data/lib/jets/pascalize.rb +9 -1
  31. data/lib/jets/poly_fun/base_executor.rb +2 -2
  32. data/lib/jets/preheat.rb +2 -2
  33. data/lib/jets/rails_overrides/common_methods.rb +1 -1
  34. data/lib/jets/resource.rb +55 -5
  35. data/lib/jets/resource/api_gateway.rb +7 -0
  36. data/lib/jets/resource/{route → api_gateway}/cors.rb +11 -10
  37. data/lib/jets/resource/api_gateway/deployment.rb +75 -0
  38. data/lib/jets/resource/{route.rb → api_gateway/method.rb} +26 -22
  39. data/lib/jets/{cfn/template_mappers/gateway_resource_mapper.rb → resource/api_gateway/resource.rb} +41 -27
  40. data/lib/jets/resource/api_gateway/rest_api.rb +23 -0
  41. data/lib/jets/resource/base.rb +17 -0
  42. data/lib/jets/resource/child_stack.rb +5 -0
  43. data/lib/jets/resource/child_stack/api_deployment.rb +58 -0
  44. data/lib/jets/resource/child_stack/api_gateway.rb +29 -0
  45. data/lib/jets/resource/child_stack/app_class.rb +81 -0
  46. data/lib/jets/resource/function.rb +184 -0
  47. data/lib/jets/resource/iam.rb +8 -0
  48. data/lib/jets/resource/iam/application_role.rb +27 -0
  49. data/lib/jets/resource/iam/base_role_definition.rb +44 -0
  50. data/lib/jets/resource/iam/class_role.rb +25 -0
  51. data/lib/jets/resource/iam/function_role.rb +25 -0
  52. data/lib/jets/{cfn/template_builders/managed_iam_policy/base_policy.rb → resource/iam/managed_policy.rb} +6 -6
  53. data/lib/jets/resource/iam/policy_document.rb +43 -0
  54. data/lib/jets/resource/permission.rb +38 -21
  55. data/lib/jets/resource/replacer.rb +50 -17
  56. data/lib/jets/resource/s3.rb +17 -0
  57. data/lib/jets/route.rb +3 -1
  58. data/lib/jets/rule/dsl.rb +7 -1
  59. data/lib/jets/server/route_matcher.rb +2 -1
  60. data/lib/jets/version.rb +1 -1
  61. metadata +46 -52
  62. data/lib/jets/cfn/template_builders.rb +0 -25
  63. data/lib/jets/cfn/template_builders/api_gateway_deployment_builder.rb +0 -38
  64. data/lib/jets/cfn/template_builders/base_child_builder.rb +0 -72
  65. data/lib/jets/cfn/template_builders/function_properties.rb +0 -6
  66. data/lib/jets/cfn/template_builders/function_properties/base_builder.rb +0 -128
  67. data/lib/jets/cfn/template_builders/function_properties/node_builder.rb +0 -12
  68. data/lib/jets/cfn/template_builders/function_properties/python_builder.rb +0 -12
  69. data/lib/jets/cfn/template_builders/function_properties/ruby_builder.rb +0 -13
  70. data/lib/jets/cfn/template_builders/iam_policy.rb +0 -6
  71. data/lib/jets/cfn/template_builders/iam_policy/application_policy.rb +0 -19
  72. data/lib/jets/cfn/template_builders/iam_policy/base_policy.rb +0 -57
  73. data/lib/jets/cfn/template_builders/iam_policy/class_policy.rb +0 -20
  74. data/lib/jets/cfn/template_builders/iam_policy/function_policy.rb +0 -21
  75. data/lib/jets/cfn/template_builders/interface.rb +0 -97
  76. data/lib/jets/cfn/template_builders/managed_iam_policy.rb +0 -6
  77. data/lib/jets/cfn/template_builders/managed_iam_policy/application_policy.rb +0 -11
  78. data/lib/jets/cfn/template_builders/managed_iam_policy/class_policy.rb +0 -10
  79. data/lib/jets/cfn/template_builders/managed_iam_policy/function_policy.rb +0 -10
  80. data/lib/jets/cfn/template_builders/parent_builder.rb +0 -95
  81. data/lib/jets/cfn/template_builders/templates/minimal-stack.yml +0 -9
  82. data/lib/jets/cfn/template_mappers.rb +0 -22
  83. data/lib/jets/cfn/template_mappers/api_gateway_deployment_mapper.rb +0 -48
  84. data/lib/jets/cfn/template_mappers/api_gateway_mapper.rb +0 -4
  85. data/lib/jets/cfn/template_mappers/child_mapper.rb +0 -41
  86. data/lib/jets/cfn/template_mappers/controller_mapper.rb +0 -36
  87. data/lib/jets/cfn/template_mappers/function_mapper.rb +0 -4
  88. data/lib/jets/cfn/template_mappers/iam_policy.rb +0 -6
  89. data/lib/jets/cfn/template_mappers/iam_policy/application_policy_mapper.rb +0 -37
  90. data/lib/jets/cfn/template_mappers/iam_policy/base_policy_mapper.rb +0 -49
  91. data/lib/jets/cfn/template_mappers/iam_policy/class_policy_mapper.rb +0 -42
  92. data/lib/jets/cfn/template_mappers/iam_policy/function_policy_mapper.rb +0 -42
  93. data/lib/jets/cfn/template_mappers/job_mapper.rb +0 -4
  94. data/lib/jets/cfn/template_mappers/lambda_function_mapper.rb +0 -52
  95. data/lib/jets/cfn/template_mappers/rule_mapper.rb +0 -5
  96. data/lib/jets/resource/attributes.rb +0 -46
  97. data/lib/jets/resource/creator.rb +0 -17
  98. data/lib/jets/resource/replacer/base.rb +0 -98
  99. data/lib/jets/resource/replacer/config_rule.rb +0 -18
  100. data/lib/jets/resource/route/attributes.rb +0 -8
@@ -0,0 +1,184 @@
1
+ class Jets::Resource
2
+ class Function < Jets::Resource::Base
3
+ def initialize(task)
4
+ @task = task
5
+ @app_class = task.class_name.to_s
6
+ end
7
+
8
+ def definition
9
+ {
10
+ function_logical_id => {
11
+ type: "AWS::Lambda::Function",
12
+ properties: combined_properties
13
+ }
14
+ }
15
+ end
16
+
17
+ def function_logical_id
18
+ "{namespace}_lambda_function".underscore
19
+ end
20
+
21
+ def replacements
22
+ @task.replacements # has namespace replacement
23
+ end
24
+
25
+ def combined_properties
26
+ props = env_file_properties
27
+ .deep_merge(global_properties)
28
+ .deep_merge(class_properties)
29
+ .deep_merge(function_properties)
30
+ finalize_properties!(props)
31
+ end
32
+
33
+ def env_file_properties
34
+ env_vars = Jets::Dotenv.load!(true)
35
+ {environment: { variables: env_vars }}
36
+ end
37
+
38
+ # Global properties example:
39
+ # jets defaults are in jets/default/application.rb.
40
+ # Your application's default config/application.rb then get used. Example:
41
+ #
42
+ # Jets.application.configure do
43
+ # config.function = ActiveSupport::OrderedOptions.new
44
+ # config.function.timeout = 10
45
+ # config.function.runtime = "nodejs8.10"
46
+ # config.function.memory_size = 1536
47
+ # end
48
+ def global_properties
49
+ baseline = {
50
+ code: {
51
+ s3_bucket: "!Ref S3Bucket",
52
+ s3_key: code_s3_key
53
+ },
54
+ role: "!Ref IamRole",
55
+ environment: { variables: environment },
56
+ }
57
+
58
+ appplication_config = Jets.application.config.function.to_h
59
+ baseline.merge(appplication_config)
60
+ end
61
+
62
+ # Class properties example:
63
+ #
64
+ # class PostsController < ApplicationController
65
+ # class_timeout 22
66
+ # ...
67
+ # end
68
+ #
69
+ # Also handles iam policy override at the class level. Example:
70
+ #
71
+ # class_iam_policy("logs:*")
72
+ #
73
+ def class_properties
74
+ # klass is PostsController, HardJob, GameRule, Hello or HelloFunction
75
+ klass = Jets::Klass.from_task(@task)
76
+ class_properties = klass.class_properties
77
+ if klass.build_class_iam?
78
+ iam_policy = Jets::Resource::Iam::ClassRole.new(klass)
79
+ class_properties[:role] = "!GetAtt #{iam_policy.logical_id}.Arn"
80
+ end
81
+ class_properties
82
+ end
83
+
84
+ # Function properties example:
85
+ #
86
+ # class PostsController < ApplicationController
87
+ # timeout 18
88
+ # def index
89
+ # ...
90
+ # end
91
+ #
92
+ # Also handles iam policy override at the function level. Example:
93
+ #
94
+ # iam_policy("ec2:*")
95
+ # def new
96
+ # render json: params.merge(action: "new")
97
+ # end
98
+ #
99
+ def function_properties
100
+ properties = @task.properties
101
+ if @task.build_function_iam?
102
+ iam_policy = Jets::Resource::Iam::FunctionRole.new(@task)
103
+ properties[:role] = "!GetAtt #{iam_policy.logical_id}.Arn"
104
+ end
105
+ properties
106
+ end
107
+
108
+ # Properties managed by Jets with more finality.
109
+ def finalize_properties!(props)
110
+ handler = full_handler(props)
111
+ runtime = get_runtime(props)
112
+ props.merge!(
113
+ function_name: function_name,
114
+ handler: handler,
115
+ runtime: runtime,
116
+ )
117
+ end
118
+
119
+ def get_runtime(props)
120
+ props[:runtime] || default_runtime
121
+ end
122
+
123
+ def default_runtime
124
+ map = {
125
+ node: "nodejs8.10",
126
+ python: "python3.6",
127
+ ruby: "nodejs8.10", # node shim for ruby support
128
+ }
129
+ map[@task.lang]
130
+ end
131
+
132
+ def default_handler
133
+ map = {
134
+ node: @task.full_handler(:handler), # IE: handlers/controllers/posts/show.handler
135
+ python: @task.full_handler(:lambda_handler), # IE: handlers/controllers/posts/show.lambda_handler
136
+ ruby: handler, # IE: handlers/controllers/posts_controllers.index
137
+ }
138
+ map[@task.lang]
139
+ end
140
+
141
+ def handler
142
+ handler_value(@task.meth) # IE: handlers/controllers/posts_controllers.index
143
+ end
144
+
145
+ # Used for node-shim also
146
+ def handler_value(meth)
147
+ "handlers/#{@task.type.pluralize}/#{@app_class.underscore}.#{meth}"
148
+ end
149
+
150
+ # Ensure that the handler path is normalized.
151
+ def full_handler(props)
152
+ if props[:handler]
153
+ handler_value(props[:handler])
154
+ else
155
+ default_handler
156
+ end
157
+ end
158
+
159
+ def code_s3_key
160
+ Jets::Naming.code_s3_key
161
+ end
162
+
163
+ # Examples:
164
+ # "#{Jets.config.project_namespace}-sleep_job-perform"
165
+ # "demo-dev-sleep_job-perform"
166
+ def function_name
167
+ # Example values:
168
+ # @app_class: admin/pages_controller
169
+ # @task.meth: index
170
+ # method: admin/pages_controller
171
+ # method: admin-pages_controller-index
172
+ method = @app_class.underscore
173
+ method = method.sub('/','-') + "-#{@task.meth}"
174
+ "#{Jets.config.project_namespace}-#{method}"
175
+ end
176
+
177
+ def environment
178
+ env = Jets.config.environment ? Jets.config.environment.to_h : {}
179
+ jets_env_options = {JETS_ENV: Jets.env.to_s}
180
+ jets_env_options[:JETS_ENV_EXTRA] = Jets.config.env_extra if Jets.config.env_extra
181
+ env.deep_merge(jets_env_options)
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,8 @@
1
+ module Jets::Resource::Iam
2
+ autoload :BaseRoleDefinition, 'jets/resource/iam/base_role_definition'
3
+ autoload :ApplicationRole, 'jets/resource/iam/application_role'
4
+ autoload :ClassRole, 'jets/resource/iam/class_role'
5
+ autoload :FunctionRole, 'jets/resource/iam/function_role'
6
+ autoload :PolicyDocument, 'jets/resource/iam/policy_document'
7
+ autoload :ManagedPolicy, 'jets/resource/iam/managed_policy'
8
+ end
@@ -0,0 +1,27 @@
1
+ module Jets::Resource::Iam
2
+ class ApplicationRole < Jets::Resource::Base
3
+ include BaseRoleDefinition
4
+
5
+ def initialize
6
+ @policy_definitions = Jets.config.iam_policy # config.iam_policy contains definitions
7
+ @policy_definitions = [@policy_definitions].flatten if @policy_definitions
8
+
9
+ @managed_policy_definitions = Jets.config.managed_iam_policy # config.managed_iam_policy contains definitions
10
+ @managed_policy_definitions = [@managed_policy_definitions].flatten if @managed_policy_definitions
11
+ end
12
+
13
+ def role_logical_id
14
+ "iam_role"
15
+ end
16
+
17
+ def role_name
18
+ "ApplicationRole" # camelized because used as template value
19
+ end
20
+
21
+ def outputs
22
+ {
23
+ logical_id => "!Ref #{logical_id}",
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ module Jets::Resource::Iam
2
+ module BaseRoleDefinition
3
+ def definition
4
+ logical_id = role_logical_id
5
+
6
+ definition = {
7
+ logical_id => {
8
+ type: "AWS::IAM::Role",
9
+ properties: {
10
+ role_name: role_name,
11
+ path: "/",
12
+ assume_role_policy_document: {
13
+ version: "2012-10-17",
14
+ statement: [{
15
+ effect: "Allow",
16
+ principal: {service: ["lambda.amazonaws.com"]},
17
+ action: ["sts:AssumeRole"]}
18
+ ]
19
+ }
20
+ }
21
+ }
22
+ }
23
+
24
+ definition[logical_id][:properties][:policies] = [
25
+ policy_name: "#{role_name}Policy",
26
+ policy_document: policy_document,
27
+ ] if policy_document
28
+
29
+ # if managed_iam_policy.arns
30
+ # definition[logical_id][:properties][:managed_policy_arns] = managed_iam_policy.arns
31
+ # end
32
+
33
+ definition
34
+ end
35
+
36
+ def policy_document
37
+ PolicyDocument.new(@policy_definitions).policy_document
38
+ end
39
+
40
+ def managed_iam_policy
41
+ ManagedPolicy.new(@managed_policy_definitions).arns
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,25 @@
1
+ module Jets::Resource::Iam
2
+ class ClassRole < Jets::Resource::Base
3
+ include BaseRoleDefinition
4
+
5
+ def initialize(app_class)
6
+ @app_class = app_class.to_s # IE: PostsController, HardJob, Hello, HelloFunction
7
+ @policy_definitions = app_class.class_iam_policy || [] # class_iam_policy contains definitions
8
+ @managed_policy_definitions = app_class.class_managed_iam_policy || [] # class_managed_iam_policy contains definitions
9
+ end
10
+
11
+ def role_logical_id
12
+ "{namespace}_iam_role".underscore
13
+ end
14
+
15
+ def role_name
16
+ "{namespace}Role" # camelized because used as template value
17
+ end
18
+
19
+ def replacements
20
+ {
21
+ namespace: @app_class.gsub('::','').camelize, # camelized because can be used as value
22
+ }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Jets::Resource::Iam
2
+ class FunctionRole < Jets::Resource::Base
3
+ include BaseRoleDefinition
4
+
5
+ def initialize(task)
6
+ @task = task
7
+ @policy_definitions = task.iam_policy || [] # iam_policy contains policy definitions
8
+ @managed_policy_definitions = task.managed_iam_policy || [] # managed_iam_policy contains policy definitions
9
+ end
10
+
11
+ def role_logical_id
12
+ "{namespace}_iam_role".underscore
13
+ end
14
+
15
+ def role_name
16
+ "{namespace}Role" # camelized because used as template value
17
+ end
18
+
19
+ def replacements
20
+ {
21
+ namespace: "#{@task.class_name.gsub('::','')}#{@task.meth.to_s.camelize}", # camelized because can be used as value
22
+ }
23
+ end
24
+ end
25
+ end
@@ -1,11 +1,11 @@
1
- # Classes that inherit this Base class should implement:
2
- #
3
- # initialize - each initializer has a different signature
4
- #
5
- module Jets::Cfn::TemplateBuilders::ManagedIamPolicy
6
- class BasePolicy
1
+ module Jets::Resource::Iam
2
+ class ManagedPolicy
7
3
  extend Memoist
4
+
8
5
  attr_reader :definitions
6
+ def initialize(*definitions)
7
+ @definitions = definitions.flatten
8
+ end
9
9
 
10
10
  def arns
11
11
  definitions.map { |definition| standardize(definition) }
@@ -0,0 +1,43 @@
1
+ module Jets::Resource::Iam
2
+ class PolicyDocument
3
+ extend Memoist
4
+
5
+ attr_reader :definitions
6
+ def initialize(*definitions)
7
+ @definitions = definitions.flatten
8
+ # empty starting policy that will be altered
9
+ @policy = {
10
+ version: "2012-10-17",
11
+ statement: []
12
+ }
13
+ # https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_sid.html
14
+ @sid = 0 # counter
15
+ end
16
+
17
+ def policy_document
18
+ definitions.map { |definition| standardize(definition) }
19
+ Jets::Pascalize.pascalize(@policy)
20
+ end
21
+ memoize :policy_document # only process policy_document once
22
+
23
+ def standardize(definition)
24
+ @sid += 1
25
+ case definition
26
+ when String
27
+ @policy[:statement] << {
28
+ sid: "Stmt#{@sid}",
29
+ action: [definition],
30
+ effect: "Allow",
31
+ resource: "*",
32
+ }
33
+ when Hash
34
+ definition = definition.stringify_keys
35
+ if definition.key?("Version") # special case where we replace the policy entirely
36
+ @policy = definition
37
+ else
38
+ @policy[:statement] << definition
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,43 +1,60 @@
1
- module Jets::Resource
1
+ class Jets::Resource
2
2
  class Permission
3
3
  extend Memoist
4
4
 
5
- def initialize(task, resource)
6
- @task = task
7
- @resource_attributes = resource
5
+ def initialize(replacements, associated_resource)
6
+ @replacements = replacements
7
+ # puts caller
8
+ # puts "replacements #{replacements.inspect}"
9
+ @associated_resource = associated_resource
8
10
  end
9
11
 
10
- def attributes
12
+ def logical_id
11
13
  logical_id = "{namespace}Permission"
12
- md = @resource_attributes.logical_id.match(/(\d+)/)
13
- if md
14
- counter = md[1]
15
- end
14
+ md = @associated_resource.logical_id.match(/(\d+)/)
15
+ counter = md[1] if md
16
16
  logical_id = [logical_id, counter].compact.join('')
17
+ # replace possible {namespace} in the logical id
18
+ logical_id = replacer.replace_value(logical_id)
19
+ Jets::Pascalize.pascalize_string(logical_id)
20
+ end
17
21
 
22
+ def type
23
+ attributes['Type']
24
+ end
25
+
26
+ def properties
27
+ attributes['Properties']
28
+ end
29
+
30
+ def attributes
18
31
  attributes = {
19
- logical_id => {
20
- type: "AWS::Lambda::Permission",
21
- properties: {
22
- function_name: "!GetAtt {namespace}LambdaFunction.Arn",
23
- action: "lambda:InvokeFunction",
24
- principal: principal,
25
- source_arn: source_arn,
26
- }
32
+ type: "AWS::Lambda::Permission",
33
+ properties: {
34
+ function_name: "!GetAtt {namespace}LambdaFunction.Arn",
35
+ action: "lambda:InvokeFunction",
36
+ principal: principal,
37
+ source_arn: source_arn,
27
38
  }
28
39
  }
29
- Attributes.new(attributes, @task)
40
+ attributes = replacer.replace_placeholders(attributes)
41
+ Jets::Pascalize.pascalize(attributes)
30
42
  end
31
43
  memoize :attributes
32
44
 
33
45
  # Auto-detect principal from the associated resources.
34
46
  def principal
35
- Replacer.principal_map(@resource_attributes.type)
47
+ Replacer.principal_map(@associated_resource.type)
36
48
  end
37
49
 
38
50
  def source_arn
39
- default_arn = "!GetAtt #{@resource_attributes.logical_id}.Arn"
40
- Replacer.source_arn_map(@resource_attributes.type) || default_arn
51
+ default_arn = "!GetAtt #{@associated_resource.logical_id}.Arn"
52
+ Replacer.source_arn_map(@associated_resource.type) || default_arn
53
+ end
54
+
55
+ def replacer
56
+ Replacer.new(@replacements)
41
57
  end
58
+ memoize :replacer
42
59
  end
43
60
  end