jets 0.8.18 → 0.9.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +0 -3
  3. data/CHANGELOG.md +20 -1
  4. data/Gemfile.lock +6 -2
  5. data/README/prerelease.md +6 -0
  6. data/README/testing.md +41 -0
  7. data/Rakefile +9 -1
  8. data/jets.gemspec +1 -0
  9. data/lib/jets.rb +17 -18
  10. data/lib/jets/application.rb +26 -3
  11. data/lib/jets/aws_services.rb +26 -59
  12. data/lib/jets/aws_services/stack_status.rb +52 -0
  13. data/lib/jets/builders.rb +3 -2
  14. data/lib/jets/builders/handler_generator.rb +38 -2
  15. data/lib/jets/builders/shared_deducer.rb +32 -0
  16. data/lib/jets/cfn/builders.rb +3 -1
  17. data/lib/jets/cfn/builders/api_deployment_builder.rb +1 -1
  18. data/lib/jets/cfn/builders/api_gateway_builder.rb +1 -1
  19. data/lib/jets/cfn/builders/base_child_builder.rb +37 -7
  20. data/lib/jets/cfn/builders/controller_builder.rb +6 -1
  21. data/lib/jets/cfn/builders/function_builder.rb +5 -0
  22. data/lib/jets/cfn/builders/interface.rb +5 -6
  23. data/lib/jets/cfn/builders/job_builder.rb +5 -0
  24. data/lib/jets/cfn/builders/parent_builder.rb +17 -16
  25. data/lib/jets/cfn/builders/rule_builder.rb +6 -1
  26. data/lib/jets/cfn/builders/shared_builder.rb +14 -0
  27. data/lib/jets/commands.rb +9 -8
  28. data/lib/jets/commands/build.rb +36 -14
  29. data/lib/jets/commands/console.rb +1 -0
  30. data/lib/jets/commands/help/runner.md +17 -0
  31. data/lib/jets/commands/main.rb +7 -0
  32. data/lib/jets/commands/new.rb +39 -19
  33. data/lib/jets/commands/runner.rb +18 -0
  34. data/lib/jets/commands/sequence.rb +27 -1
  35. data/lib/jets/commands/templates/skeleton/.rspec +3 -0
  36. data/lib/jets/commands/templates/skeleton/Gemfile.tt +0 -1
  37. data/lib/jets/commands/templates/skeleton/app/jobs/application_job.rb +2 -0
  38. data/lib/jets/commands/templates/skeleton/config/application.rb.tt +2 -1
  39. data/lib/jets/commands/templates/skeleton/config/routes.rb +5 -1
  40. data/lib/jets/commands/templates/skeleton/spec/spec_helper.rb.tt +5 -4
  41. data/lib/jets/core.rb +8 -6
  42. data/lib/jets/default/application.rb +1 -0
  43. data/lib/jets/generator.rb +1 -1
  44. data/lib/jets/inflections.rb +23 -0
  45. data/lib/jets/job/dsl.rb +69 -47
  46. data/lib/jets/klass.rb +6 -1
  47. data/lib/jets/lambda/dsl.rb +102 -34
  48. data/lib/jets/lambda/function_constructor.rb +2 -2
  49. data/lib/jets/lambda/task.rb +10 -5
  50. data/lib/jets/naming.rb +13 -2
  51. data/lib/jets/processors/deducer.rb +13 -2
  52. data/lib/jets/processors/main_processor.rb +1 -1
  53. data/lib/jets/rails_overrides.rb +1 -1
  54. data/lib/jets/resource.rb +20 -5
  55. data/lib/jets/resource/api_gateway/deployment.rb +0 -1
  56. data/lib/jets/resource/associated.rb +26 -0
  57. data/lib/jets/resource/base.rb +12 -0
  58. data/lib/jets/resource/child_stack.rb +2 -0
  59. data/lib/jets/resource/child_stack/api_deployment.rb +9 -15
  60. data/lib/jets/resource/child_stack/api_gateway.rb +8 -8
  61. data/lib/jets/resource/child_stack/app_class.rb +41 -16
  62. data/lib/jets/resource/child_stack/base.rb +24 -0
  63. data/lib/jets/resource/child_stack/shared.rb +90 -0
  64. data/lib/jets/resource/config.rb +4 -0
  65. data/lib/jets/resource/config/config_rule.rb +66 -0
  66. data/lib/jets/resource/config/managed_rule.rb +15 -0
  67. data/lib/jets/resource/events.rb +3 -0
  68. data/lib/jets/resource/events/rule.rb +31 -0
  69. data/lib/jets/resource/iam/application_role.rb +2 -2
  70. data/lib/jets/resource/iam/base_role_definition.rb +4 -2
  71. data/lib/jets/resource/iam/class_role.rb +50 -2
  72. data/lib/jets/resource/iam/function_role.rb +28 -0
  73. data/lib/jets/resource/iam/policy_document.rb +0 -4
  74. data/lib/jets/resource/permission.rb +12 -6
  75. data/lib/jets/resource/replacer.rb +4 -0
  76. data/lib/jets/resource/sns.rb +3 -0
  77. data/lib/jets/resource/standardizer.rb +42 -0
  78. data/lib/jets/router.rb +9 -1
  79. data/lib/jets/rule/dsl.rb +51 -78
  80. data/lib/jets/stack.rb +105 -0
  81. data/lib/jets/stack/builder.rb +38 -0
  82. data/lib/jets/stack/definition.rb +50 -0
  83. data/lib/jets/stack/function.rb +60 -0
  84. data/lib/jets/stack/main.rb +5 -0
  85. data/lib/jets/stack/main/dsl.rb +33 -0
  86. data/lib/jets/stack/main/extensions/base.rb +45 -0
  87. data/lib/jets/stack/main/extensions/cloudwatch.rb +19 -0
  88. data/lib/jets/stack/main/extensions/lambda.rb +69 -0
  89. data/lib/jets/stack/main/extensions/sns.rb +12 -0
  90. data/lib/jets/stack/main/extensions/sqs.rb +8 -0
  91. data/lib/jets/stack/output.rb +38 -0
  92. data/lib/jets/stack/output/dsl.rb +19 -0
  93. data/lib/jets/stack/output/lookup.rb +36 -0
  94. data/lib/jets/stack/parameter.rb +38 -0
  95. data/lib/jets/stack/parameter/dsl.rb +42 -0
  96. data/lib/jets/stack/resource.rb +30 -0
  97. data/lib/jets/stack/resource/dsl.rb +19 -0
  98. data/lib/jets/version.rb +1 -1
  99. metadata +53 -4
  100. data/support/clean +0 -3
  101. data/support/console +0 -3
@@ -1,9 +1,10 @@
1
+ # Implements:
2
+ #
3
+ # definition
4
+ # template_filename
5
+ #
1
6
  module Jets::Resource::ChildStack
2
- class ApiGateway < Jets::Resource::Base
3
- def initialize(s3_bucket)
4
- @s3_bucket = s3_bucket
5
- end
6
-
7
+ class ApiGateway < Base
7
8
  def definition
8
9
  {
9
10
  api_gateway: {
@@ -21,9 +22,8 @@ module Jets::Resource::ChildStack
21
22
  }
22
23
  end
23
24
 
24
- def template_url
25
- path = File.basename("#{Jets.config.project_namespace}-api-gateway.yml")
26
- "https://s3.amazonaws.com/#{@s3_bucket}/jets/cfn-templates/#{path}"
25
+ def template_filename
26
+ "#{Jets.config.project_namespace}-api-gateway.yml"
27
27
  end
28
28
  end
29
29
  end
@@ -1,13 +1,18 @@
1
+ # Implements:
2
+ #
3
+ # definition
4
+ # template_filename
5
+ #
1
6
  module Jets::Resource::ChildStack
2
- class AppClass < Jets::Resource::Base
3
- def initialize(path, s3_bucket)
4
- @path = path
5
- @s3_bucket = s3_bucket
7
+ class AppClass < Base
8
+ def initialize(s3_bucket, options={})
9
+ super
10
+ @path = options[:path]
6
11
  end
7
12
 
8
13
  def definition
9
14
  logical_id = app_logical_id
10
- {
15
+ defintion = {
11
16
  logical_id => {
12
17
  type: "AWS::CloudFormation::Stack",
13
18
  properties: {
@@ -16,6 +21,32 @@ module Jets::Resource::ChildStack
16
21
  }
17
22
  }
18
23
  }
24
+ defintion[logical_id][:depends_on] = depends_on if depends_on
25
+ defintion
26
+ end
27
+
28
+ def depends_on
29
+ klass = current_app_class.constantize
30
+ return unless klass.depends_on
31
+
32
+ klass.depends_on.map do |shared_stack|
33
+ shared_stack.to_s.camelize # logical_id
34
+ end
35
+ end
36
+
37
+ def depends_on_params
38
+ params = {}
39
+ depends_on.each do |dependency|
40
+ dependency_outputs(dependency).each do |output|
41
+ dependency_class = dependency.to_s.classify
42
+ params[output] = "!GetAtt #{dependency_class}.Outputs.#{output}"
43
+ end
44
+ end
45
+ params
46
+ end
47
+
48
+ def dependency_outputs(dependency)
49
+ dependency.to_s.classify.constantize.output_keys
19
50
  end
20
51
 
21
52
  def parameters
@@ -24,6 +55,7 @@ module Jets::Resource::ChildStack
24
55
  S3Bucket: "!Ref S3Bucket",
25
56
  }
26
57
  common.merge!(controller_params) if controller?
58
+ common.merge!(depends_on_params) if depends_on
27
59
  common
28
60
  end
29
61
 
@@ -51,31 +83,24 @@ module Jets::Resource::ChildStack
51
83
  end
52
84
 
53
85
  def current_app_class
54
- templates_prefix = "#{Jets::Naming.template_path_prefix}-"
86
+ templates_prefix = "#{Jets::Naming.template_path_prefix}-app-"
55
87
  @path.sub(templates_prefix, '')
56
88
  .sub(/\.yml$/,'')
57
89
  .gsub('-','/')
58
90
  .classify
59
91
  end
60
92
 
61
- def outputs
62
- {
63
- logical_id => "!Ref #{logical_id}",
64
- }
65
- end
66
-
67
- # Dont name logical id because that is in Jets::Resource
68
93
  # map the path to a camelized logical_id. Example:
69
94
  # /tmp/jets/demo/templates/demo-dev-2-posts_controller.yml to
70
95
  # PostsController
71
96
  def app_logical_id
72
- regexp = Regexp.new(".*#{Jets.config.project_namespace}-")
97
+ regexp = Regexp.new(".*#{Jets.config.project_namespace}-app-")
73
98
  controller_name = @path.sub(regexp, '').sub('.yml', '')
74
99
  controller_name.underscore.camelize
75
100
  end
76
101
 
77
- def template_url
78
- "https://s3.amazonaws.com/#{@s3_bucket}/jets/cfn-templates/#{File.basename(@path)}"
102
+ def template_filename
103
+ @path
79
104
  end
80
105
  end
81
106
  end
@@ -0,0 +1,24 @@
1
+ # Inheriting classes should implement:
2
+ #
3
+ # definition
4
+ # template_filename
5
+ #
6
+ module Jets::Resource::ChildStack
7
+ class Base < Jets::Resource::Base
8
+ def initialize(s3_bucket, options={})
9
+ @s3_bucket = s3_bucket
10
+ @options = options
11
+ end
12
+
13
+ def outputs
14
+ {
15
+ logical_id => "!Ref #{logical_id}",
16
+ }
17
+ end
18
+
19
+ def template_url
20
+ basename = File.basename(template_filename)
21
+ "https://s3.amazonaws.com/#{@s3_bucket}/jets/cfn-templates/#{basename}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,90 @@
1
+ # Implements:
2
+ #
3
+ # definition
4
+ # template_filename
5
+ #
6
+ module Jets::Resource::ChildStack
7
+ class Shared < AppClass
8
+ def initialize(s3_bucket, options={})
9
+ super
10
+ @path = options[:path]
11
+ end
12
+
13
+ def definition
14
+ logical_id = shared_logical_id
15
+ definition = {
16
+ logical_id => {
17
+ type: "AWS::CloudFormation::Stack",
18
+ properties: child_properties
19
+ }
20
+ }
21
+ definition[logical_id][:depends_on] = depends_on if depends_on
22
+ definition
23
+ end
24
+
25
+ def child_properties
26
+ props = {
27
+ template_url: template_url,
28
+ }
29
+
30
+ props[:parameters] = common_parameters # common child parameters
31
+ # add depends on parameters
32
+ depends_on.each do |dependency|
33
+ dependency_outputs(dependency).each do |output|
34
+ dependency_class = dependency.to_s.classify
35
+ props[:parameters][output] = "!GetAtt #{dependency_class}.Outputs.#{output}"
36
+ end
37
+ end if depends_on
38
+
39
+ props
40
+ end
41
+
42
+ def common_parameters
43
+ {
44
+ IamRole: "!GetAtt IamRole.Arn",
45
+ S3Bucket: "!Ref S3Bucket",
46
+ }
47
+ end
48
+
49
+ # Returns output keys associated with the stack. They are the resource logical ids.
50
+ def dependency_outputs(dependency)
51
+ dependency.to_s.classify.constantize.output_keys
52
+ end
53
+
54
+ def depends_on
55
+ return unless current_shared_class.depends_on
56
+ current_shared_class.depends_on.map { |x| x.to_s.singularize.camelize }
57
+ end
58
+
59
+ # map the path to a camelized logical_id. Example:
60
+ # /tmp/jets/demo/templates/demo-dev-2-shared-resources.yml to
61
+ # PostsController
62
+ def shared_logical_id
63
+ regexp = Regexp.new(".*#{Jets.config.project_namespace}-shared-") # remove the shared
64
+ shared_name = @path.sub(regexp, '').sub('.yml', '')
65
+ shared_name.underscore.camelize
66
+ end
67
+
68
+ # IE: app/resource.rb => Resource
69
+ # Returns Resource class object in the example
70
+ def current_shared_class
71
+ templates_prefix = "#{Jets::Naming.template_path_prefix}-shared-"
72
+ @path.sub(templates_prefix, '')
73
+ .sub(/\.yml$/,'')
74
+ .gsub('-','/')
75
+ .classify
76
+ .constantize # returns actual class
77
+ end
78
+
79
+ # Tells us if there are any resources defined in the shared class.
80
+ #
81
+ # Returns: Boolean
82
+ def resources?
83
+ current_shared_class.build?
84
+ end
85
+
86
+ def template_filename
87
+ "#{Jets.config.project_namespace}-shared-#{current_shared_class.to_s.underscore}.yml"
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,4 @@
1
+ module Jets::Resource::Config
2
+ autoload :ConfigRule, 'jets/resource/config/config_rule'
3
+ autoload :ManagedRule, 'jets/resource/config/managed_rule'
4
+ end
@@ -0,0 +1,66 @@
1
+ module Jets::Resource::Config
2
+ class ConfigRule < Jets::Resource::Base
3
+ def initialize(app_class, meth, props={})
4
+ @app_class = app_class.to_s
5
+ @meth = meth
6
+ @props = props # associated_properties from dsl.rb
7
+ end
8
+
9
+ def definition
10
+ {
11
+ config_rule_logical_id => {
12
+ type: "AWS::Config::ConfigRule",
13
+ properties: definition_properties,
14
+ }
15
+ }
16
+ end
17
+
18
+ # Do not name this method properties, that is a computed method of `Jets::Resource::Base`
19
+ def definition_properties
20
+ {
21
+ config_rule_name: config_rule_name,
22
+ source: {
23
+ owner: "CUSTOM_LAMBDA",
24
+ source_identifier: "!GetAtt {namespace}LambdaFunction.Arn",
25
+ source_details: [
26
+ {
27
+ event_source: "aws.config",
28
+ message_type: "ConfigurationItemChangeNotification"
29
+ },
30
+ {
31
+ event_source: "aws.config",
32
+ message_type: "OversizedConfigurationItemChangeNotification"
33
+ }
34
+ ]
35
+ },
36
+ }.deep_merge(@props)
37
+ end
38
+
39
+ def config_rule_logical_id
40
+ "{namespace}_config_rule"
41
+ end
42
+
43
+ def config_rule_name
44
+ app_class = @app_class.underscore.gsub(/_rule$/,'')
45
+ ns = namespace
46
+ ns = nil if ns == false # for compact
47
+ [ns, "#{app_class}_#{@meth}"].compact.join('_').dasherize
48
+ end
49
+
50
+ def namespace
51
+ namespace = nil
52
+ klass = @app_class.constantize
53
+ while klass != Jets::Lambda::Functions
54
+ namespace = klass.rule_namespace
55
+ break if namespace or namespace == false
56
+ klass = klass.superclass
57
+ end
58
+
59
+ if namespace.nil?
60
+ Jets.config.project_namespace
61
+ else
62
+ namespace
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,15 @@
1
+ # ManagedRule is just different enough to be a separate class vs being part of the
2
+ # ConfigRule class itself.
3
+ module Jets::Resource::Config
4
+ class ManagedRule < ConfigRule
5
+ def definition_properties
6
+ {
7
+ config_rule_name: config_rule_name,
8
+ source: {
9
+ owner: "AWS",
10
+ source_identifier: @meth.upcase,
11
+ },
12
+ }.deep_merge(@props)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Jets::Resource::Events
2
+ autoload :Rule, 'jets/resource/events/rule'
3
+ end
@@ -0,0 +1,31 @@
1
+ module Jets::Resource::Events
2
+ class Rule < Jets::Resource::Base
3
+ def initialize(props)
4
+ @props = props # associated_properties from dsl.rb
5
+ end
6
+
7
+ def definition
8
+ {
9
+ rule_logical_id => {
10
+ type: "AWS::Events::Rule",
11
+ properties: merged_properties
12
+ }
13
+ }
14
+ end
15
+
16
+ # Do not name this method properties, that is a computed method of `Jets::Resource::Base`
17
+ def merged_properties
18
+ {
19
+ state: "ENABLED",
20
+ targets: [{
21
+ arn: "!GetAtt {namespace}LambdaFunction.Arn",
22
+ id: "{namespace}RuleTarget"
23
+ }]
24
+ }.deep_merge(@props)
25
+ end
26
+
27
+ def rule_logical_id
28
+ "{namespace}_events_rule"
29
+ end
30
+ end
31
+ end
@@ -4,10 +4,10 @@ module Jets::Resource::Iam
4
4
 
5
5
  def initialize
6
6
  @policy_definitions = Jets.config.iam_policy # config.iam_policy contains definitions
7
- @policy_definitions = [@policy_definitions].flatten if @policy_definitions
7
+ @policy_definitions = @policy_definitions ? [@policy_definitions].flatten : []
8
8
 
9
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
10
+ @managed_policy_definitions = @managed_policy_definitions ? [@managed_policy_definitions].flatten : []
11
11
  end
12
12
 
13
13
  def role_logical_id
@@ -1,5 +1,7 @@
1
1
  module Jets::Resource::Iam
2
2
  module BaseRoleDefinition
3
+ attr_reader :policy_definitions, :managed_policy_definitions
4
+
3
5
  def definition
4
6
  logical_id = role_logical_id
5
7
 
@@ -34,11 +36,11 @@ module Jets::Resource::Iam
34
36
  end
35
37
 
36
38
  def policy_document
37
- PolicyDocument.new(@policy_definitions).policy_document
39
+ PolicyDocument.new(@policy_definitions.uniq).policy_document
38
40
  end
39
41
 
40
42
  def managed_policy_arns
41
- ManagedPolicy.new(@managed_policy_definitions).arns
43
+ ManagedPolicy.new(@managed_policy_definitions.uniq).arns
42
44
  end
43
45
  end
44
46
  end
@@ -4,8 +4,8 @@ module Jets::Resource::Iam
4
4
 
5
5
  def initialize(app_class)
6
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
7
+ @policy_definitions = lookup_iam_policies
8
+ @managed_policy_definitions = lookup_managed_iam_policies
9
9
  end
10
10
 
11
11
  def role_logical_id
@@ -22,5 +22,53 @@ module Jets::Resource::Iam
22
22
  namespace: @app_class.gsub('::','').camelize, # camelized because can be used as value
23
23
  }
24
24
  end
25
+
26
+ def policy_document
27
+ # Handles precedence inheritance from the ApplicationRole to the ClassRole
28
+ @policy_definitions += application_role.policy_definitions if inherit?
29
+ super
30
+ end
31
+
32
+ def managed_policy_arns
33
+ @managed_policy_definitions += application_role.managed_policy_definitions if inherit?
34
+ super
35
+ end
36
+
37
+ # There are 2 types of inheritance: from superclasses and from higher precedence policies.
38
+ # This one manages the inheritance for higher precedence policies.
39
+ def inherit?
40
+ !@policy_definitions.empty? || !@managed_policy_definitions.empty?
41
+ end
42
+
43
+ def application_role
44
+ Jets::Resource::Iam::ApplicationRole.new
45
+ end
46
+ memoize :application_role
47
+
48
+ # Accounts for inherited class_managed_iam_policy from superclasses
49
+ def lookup_managed_iam_policies
50
+ all_classes.map do |k|
51
+ k.class_managed_iam_policy # class_managed_iam_policy contains definitions
52
+ end.uniq
53
+ end
54
+
55
+ # Accounts for inherited class_iam_policies from superclasses
56
+ def lookup_iam_policies
57
+ all_classes.map do |k|
58
+ k.class_iam_policy # class_iam_policy contains definitions
59
+ end.uniq
60
+ end
61
+
62
+ # Class heirachry in top to down order
63
+ def all_classes
64
+ klass = @app_class.constantize
65
+ all_classes = []
66
+ while klass != Object
67
+ all_classes << klass
68
+ klass = klass.superclass
69
+ end
70
+ all_classes.reverse
71
+ end
72
+ memoize :all_classes
25
73
  end
26
74
  end