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.
- checksums.yaml +4 -4
- data/.gitmodules +0 -3
- data/CHANGELOG.md +20 -1
- data/Gemfile.lock +6 -2
- data/README/prerelease.md +6 -0
- data/README/testing.md +41 -0
- data/Rakefile +9 -1
- data/jets.gemspec +1 -0
- data/lib/jets.rb +17 -18
- data/lib/jets/application.rb +26 -3
- data/lib/jets/aws_services.rb +26 -59
- data/lib/jets/aws_services/stack_status.rb +52 -0
- data/lib/jets/builders.rb +3 -2
- data/lib/jets/builders/handler_generator.rb +38 -2
- data/lib/jets/builders/shared_deducer.rb +32 -0
- data/lib/jets/cfn/builders.rb +3 -1
- data/lib/jets/cfn/builders/api_deployment_builder.rb +1 -1
- data/lib/jets/cfn/builders/api_gateway_builder.rb +1 -1
- data/lib/jets/cfn/builders/base_child_builder.rb +37 -7
- data/lib/jets/cfn/builders/controller_builder.rb +6 -1
- data/lib/jets/cfn/builders/function_builder.rb +5 -0
- data/lib/jets/cfn/builders/interface.rb +5 -6
- data/lib/jets/cfn/builders/job_builder.rb +5 -0
- data/lib/jets/cfn/builders/parent_builder.rb +17 -16
- data/lib/jets/cfn/builders/rule_builder.rb +6 -1
- data/lib/jets/cfn/builders/shared_builder.rb +14 -0
- data/lib/jets/commands.rb +9 -8
- data/lib/jets/commands/build.rb +36 -14
- data/lib/jets/commands/console.rb +1 -0
- data/lib/jets/commands/help/runner.md +17 -0
- data/lib/jets/commands/main.rb +7 -0
- data/lib/jets/commands/new.rb +39 -19
- data/lib/jets/commands/runner.rb +18 -0
- data/lib/jets/commands/sequence.rb +27 -1
- data/lib/jets/commands/templates/skeleton/.rspec +3 -0
- data/lib/jets/commands/templates/skeleton/Gemfile.tt +0 -1
- data/lib/jets/commands/templates/skeleton/app/jobs/application_job.rb +2 -0
- data/lib/jets/commands/templates/skeleton/config/application.rb.tt +2 -1
- data/lib/jets/commands/templates/skeleton/config/routes.rb +5 -1
- data/lib/jets/commands/templates/skeleton/spec/spec_helper.rb.tt +5 -4
- data/lib/jets/core.rb +8 -6
- data/lib/jets/default/application.rb +1 -0
- data/lib/jets/generator.rb +1 -1
- data/lib/jets/inflections.rb +23 -0
- data/lib/jets/job/dsl.rb +69 -47
- data/lib/jets/klass.rb +6 -1
- data/lib/jets/lambda/dsl.rb +102 -34
- data/lib/jets/lambda/function_constructor.rb +2 -2
- data/lib/jets/lambda/task.rb +10 -5
- data/lib/jets/naming.rb +13 -2
- data/lib/jets/processors/deducer.rb +13 -2
- data/lib/jets/processors/main_processor.rb +1 -1
- data/lib/jets/rails_overrides.rb +1 -1
- data/lib/jets/resource.rb +20 -5
- data/lib/jets/resource/api_gateway/deployment.rb +0 -1
- data/lib/jets/resource/associated.rb +26 -0
- data/lib/jets/resource/base.rb +12 -0
- data/lib/jets/resource/child_stack.rb +2 -0
- data/lib/jets/resource/child_stack/api_deployment.rb +9 -15
- data/lib/jets/resource/child_stack/api_gateway.rb +8 -8
- data/lib/jets/resource/child_stack/app_class.rb +41 -16
- data/lib/jets/resource/child_stack/base.rb +24 -0
- data/lib/jets/resource/child_stack/shared.rb +90 -0
- data/lib/jets/resource/config.rb +4 -0
- data/lib/jets/resource/config/config_rule.rb +66 -0
- data/lib/jets/resource/config/managed_rule.rb +15 -0
- data/lib/jets/resource/events.rb +3 -0
- data/lib/jets/resource/events/rule.rb +31 -0
- data/lib/jets/resource/iam/application_role.rb +2 -2
- data/lib/jets/resource/iam/base_role_definition.rb +4 -2
- data/lib/jets/resource/iam/class_role.rb +50 -2
- data/lib/jets/resource/iam/function_role.rb +28 -0
- data/lib/jets/resource/iam/policy_document.rb +0 -4
- data/lib/jets/resource/permission.rb +12 -6
- data/lib/jets/resource/replacer.rb +4 -0
- data/lib/jets/resource/sns.rb +3 -0
- data/lib/jets/resource/standardizer.rb +42 -0
- data/lib/jets/router.rb +9 -1
- data/lib/jets/rule/dsl.rb +51 -78
- data/lib/jets/stack.rb +105 -0
- data/lib/jets/stack/builder.rb +38 -0
- data/lib/jets/stack/definition.rb +50 -0
- data/lib/jets/stack/function.rb +60 -0
- data/lib/jets/stack/main.rb +5 -0
- data/lib/jets/stack/main/dsl.rb +33 -0
- data/lib/jets/stack/main/extensions/base.rb +45 -0
- data/lib/jets/stack/main/extensions/cloudwatch.rb +19 -0
- data/lib/jets/stack/main/extensions/lambda.rb +69 -0
- data/lib/jets/stack/main/extensions/sns.rb +12 -0
- data/lib/jets/stack/main/extensions/sqs.rb +8 -0
- data/lib/jets/stack/output.rb +38 -0
- data/lib/jets/stack/output/dsl.rb +19 -0
- data/lib/jets/stack/output/lookup.rb +36 -0
- data/lib/jets/stack/parameter.rb +38 -0
- data/lib/jets/stack/parameter/dsl.rb +42 -0
- data/lib/jets/stack/resource.rb +30 -0
- data/lib/jets/stack/resource/dsl.rb +19 -0
- data/lib/jets/version.rb +1 -1
- metadata +53 -4
- data/support/clean +0 -3
- data/support/console +0 -3
@@ -22,5 +22,33 @@ module Jets::Resource::Iam
|
|
22
22
|
namespace: "#{@task.class_name.gsub('::','')}#{@task.meth.to_s.camelize}", # camelized because can be used as value
|
23
23
|
}
|
24
24
|
end
|
25
|
+
|
26
|
+
def policy_document
|
27
|
+
if inherit?
|
28
|
+
@policy_definitions += class_role.policy_definitions + application_role.policy_definitions
|
29
|
+
end
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def managed_policy_arns
|
34
|
+
if inherit?
|
35
|
+
@managed_policy_definitions += class_role.managed_policy_definitions + application_role.managed_policy_definitions
|
36
|
+
end
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def inherit?
|
41
|
+
!@policy_definitions.empty? || !@managed_policy_definitions.empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
def class_role
|
45
|
+
Jets::Resource::Iam::ClassRole.new(@task.class_name.constantize)
|
46
|
+
end
|
47
|
+
memoize :class_role
|
48
|
+
|
49
|
+
def application_role
|
50
|
+
Jets::Resource::Iam::ApplicationRole.new
|
51
|
+
end
|
52
|
+
memoize :application_role
|
25
53
|
end
|
26
54
|
end
|
@@ -10,8 +10,6 @@ module Jets::Resource::Iam
|
|
10
10
|
version: "2012-10-17",
|
11
11
|
statement: []
|
12
12
|
}
|
13
|
-
# https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_sid.html
|
14
|
-
@sid = 0 # counter
|
15
13
|
end
|
16
14
|
|
17
15
|
def policy_document
|
@@ -21,13 +19,11 @@ module Jets::Resource::Iam
|
|
21
19
|
memoize :policy_document # only process policy_document once
|
22
20
|
|
23
21
|
def standardize(definition)
|
24
|
-
@sid += 1
|
25
22
|
case definition
|
26
23
|
when String
|
27
24
|
# Expands simple string from: logs => logs:*
|
28
25
|
definition = "#{definition}:*" unless definition.include?(':')
|
29
26
|
@policy[:statement] << {
|
30
|
-
sid: "Stmt#{@sid}",
|
31
27
|
action: [definition],
|
32
28
|
effect: "Allow",
|
33
29
|
resource: "*",
|
@@ -6,17 +6,24 @@ class Jets::Resource
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def definition
|
9
|
-
|
10
|
-
|
9
|
+
logical_id = permission_logical_id
|
10
|
+
|
11
|
+
definition = {
|
12
|
+
logical_id => {
|
11
13
|
type: "AWS::Lambda::Permission",
|
12
14
|
properties: {
|
13
15
|
function_name: "!GetAtt {namespace}LambdaFunction.Arn",
|
14
16
|
action: "lambda:InvokeFunction",
|
15
|
-
principal: principal
|
16
|
-
source_arn: source_arn,
|
17
|
+
principal: principal
|
17
18
|
}
|
18
19
|
}
|
19
20
|
}
|
21
|
+
|
22
|
+
# From AWS docs: https://amzn.to/2N0QXQL
|
23
|
+
# source_arn is "not supported by all event sources"
|
24
|
+
definition[logical_id][:properties][:source_arn] = source_arn if source_arn
|
25
|
+
|
26
|
+
definition
|
20
27
|
end
|
21
28
|
|
22
29
|
def permission_logical_id
|
@@ -32,8 +39,7 @@ class Jets::Resource
|
|
32
39
|
end
|
33
40
|
|
34
41
|
def source_arn
|
35
|
-
|
36
|
-
Replacer.source_arn_map(@associated_resource.type) || default_arn
|
42
|
+
Replacer.source_arn_map(@associated_resource.type)
|
37
43
|
end
|
38
44
|
end
|
39
45
|
end
|
@@ -62,6 +62,10 @@ class Jets::Resource
|
|
62
62
|
"#{service}.amazonaws.com"
|
63
63
|
end
|
64
64
|
|
65
|
+
# From AWS docs: https://amzn.to/2N0QXQL
|
66
|
+
# source_arn is "not supported by all event sources"
|
67
|
+
#
|
68
|
+
# When it is not available the resource definition should add it.
|
65
69
|
def source_arn_map(type)
|
66
70
|
map = {
|
67
71
|
"AWS::ApiGateway::Method" => "!Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*",
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Jets::Resource
|
2
|
+
class Standardizer
|
3
|
+
attr_reader :definition
|
4
|
+
def initialize(*definition)
|
5
|
+
@definition = definition.flatten
|
6
|
+
end
|
7
|
+
|
8
|
+
def template
|
9
|
+
camelize(standarize(@definition))
|
10
|
+
end
|
11
|
+
|
12
|
+
def camelize(attributes)
|
13
|
+
Jets::Camelizer.transform(attributes)
|
14
|
+
end
|
15
|
+
|
16
|
+
def standarize(definition)
|
17
|
+
first, second, third, _ = definition
|
18
|
+
if definition.size == 1 && first.is_a?(Hash) # long form
|
19
|
+
first # pass through
|
20
|
+
elsif definition.size == 2 && second.is_a?(Hash) # medium form
|
21
|
+
logical_id, attributes = first, second
|
22
|
+
attributes.delete(:properties) if attributes[:properties].nil? || attributes[:properties].empty?
|
23
|
+
{ logical_id => attributes }
|
24
|
+
elsif definition.size == 2 && second.is_a?(String) # short form
|
25
|
+
logical_id, type = first, second
|
26
|
+
{ logical_id => {
|
27
|
+
type: type
|
28
|
+
}}
|
29
|
+
elsif definition.size == 3 && (second.is_a?(String) || second.is_a?(NilClass))# short form
|
30
|
+
logical_id, type, properties = first, second, third
|
31
|
+
template = { logical_id => {
|
32
|
+
type: type
|
33
|
+
}}
|
34
|
+
attributes = template.values.first
|
35
|
+
attributes[:properties] = properties unless properties.empty?
|
36
|
+
template
|
37
|
+
else # Dont understand this form
|
38
|
+
raise "Invalid form provided. definition #{definition.inspect}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/jets/router.rb
CHANGED
@@ -30,7 +30,15 @@ module Jets
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def api_mode?
|
33
|
-
Jets.config.api_generator
|
33
|
+
if Jets.config.api_generator
|
34
|
+
puts <<~EOL.colorize(:yellow)
|
35
|
+
DEPRECATED: Jets.config.api_generator
|
36
|
+
Instead, please update your config/application.rb to use:
|
37
|
+
Jets.config.api_mode
|
38
|
+
EOL
|
39
|
+
end
|
40
|
+
api_mode = Jets.config.api_mode || Jets.config.api_generator
|
41
|
+
api_mode
|
34
42
|
end
|
35
43
|
|
36
44
|
def create_route(options)
|
data/lib/jets/rule/dsl.rb
CHANGED
@@ -3,12 +3,22 @@
|
|
3
3
|
# So the Jets::Rule::Dsl overrides some of the Jets::Lambda::Functions behavior.
|
4
4
|
#
|
5
5
|
# Implements:
|
6
|
-
#
|
6
|
+
#
|
7
|
+
# default_associated_resource_definition
|
8
|
+
#
|
7
9
|
module Jets::Rule::Dsl
|
8
10
|
extend ActiveSupport::Concern
|
9
11
|
|
10
12
|
included do
|
11
13
|
class << self
|
14
|
+
def rule_namespace(value=nil)
|
15
|
+
if value.nil?
|
16
|
+
@rule_namespace # getter
|
17
|
+
else
|
18
|
+
@rule_namespace = value # # setter
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
12
22
|
# Allows for different types of values. Examples:
|
13
23
|
#
|
14
24
|
# String: scope "AWS::EC2::SecurityGroup"
|
@@ -23,102 +33,65 @@ module Jets::Rule::Dsl
|
|
23
33
|
else # default to hash
|
24
34
|
value
|
25
35
|
end
|
26
|
-
|
36
|
+
associated_properties(scope: scope)
|
27
37
|
end
|
28
38
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
39
|
+
# Convenience method that set properties. List based on https://amzn.to/2oSph1P
|
40
|
+
# Not all properties are included because some properties are not meant to be set
|
41
|
+
# directly. For example, function_name is a calculated setting by Jets.
|
42
|
+
ASSOCIATED_PROPERTIES = %W[
|
43
|
+
config_rule_name
|
44
|
+
description
|
45
|
+
input_parameters
|
46
|
+
maximum_execution_frequency
|
47
|
+
]
|
48
|
+
define_associated_properties(ASSOCIATED_PROPERTIES)
|
36
49
|
alias_method :desc, :description
|
37
50
|
|
38
|
-
def
|
39
|
-
|
51
|
+
def default_associated_resource_definition(meth)
|
52
|
+
config_rule_definition(meth)
|
40
53
|
end
|
41
54
|
|
42
|
-
def
|
43
|
-
|
55
|
+
def config_rule_definition(meth)
|
56
|
+
resource = Jets::Resource::Config::ConfigRule.new(self, meth, associated_properties)
|
57
|
+
resource.definition # returns a definition to be added by associated_resources
|
44
58
|
end
|
45
59
|
|
46
|
-
def
|
47
|
-
update_properties(source: value)
|
48
|
-
end
|
49
|
-
|
50
|
-
def default_associated_resource
|
51
|
-
config_rule
|
52
|
-
end
|
53
|
-
|
54
|
-
def config_rule(props={})
|
55
|
-
default_props = {
|
56
|
-
config_rule_name: "{config_rule_name}",
|
57
|
-
source: {
|
58
|
-
owner: "CUSTOM_LAMBDA",
|
59
|
-
source_identifier: "{namespace}LambdaFunction.Arn",
|
60
|
-
source_details: [
|
61
|
-
{
|
62
|
-
event_source: "aws.config",
|
63
|
-
message_type: "ConfigurationItemChangeNotification"
|
64
|
-
},
|
65
|
-
{
|
66
|
-
event_source: "aws.config",
|
67
|
-
message_type: "OversizedConfigurationItemChangeNotification"
|
68
|
-
}
|
69
|
-
]
|
70
|
-
}
|
71
|
-
}
|
72
|
-
properties = default_props.deep_merge(props)
|
73
|
-
|
74
|
-
resource("{namespace}ConfigRule" => {
|
75
|
-
type: "AWS::Config::ConfigRule",
|
76
|
-
properties: properties
|
77
|
-
})
|
78
|
-
@resources # must return @resoures for update_properties
|
79
|
-
end
|
80
|
-
|
81
|
-
def managed_rule(name, props={})
|
60
|
+
def managed_rule(name)
|
82
61
|
name = name.to_s
|
62
|
+
managed_rule = Jets::Resource::Config::ManagedRule.new(self, name, associated_properties)
|
63
|
+
resource(managed_rule.definition) # Sets @associated_resources
|
83
64
|
|
84
|
-
#
|
85
|
-
name_without_rule = self.name.underscore.gsub(/_rule$/,'')
|
86
|
-
config_rule_name = "#{name_without_rule}_#{name}".dasherize
|
87
|
-
source_identifier = name.upcase
|
88
|
-
|
89
|
-
default_props = {
|
90
|
-
config_rule_name: config_rule_name,
|
91
|
-
source: {
|
92
|
-
owner: "AWS",
|
93
|
-
source_identifier: source_identifier,
|
94
|
-
}
|
95
|
-
}
|
96
|
-
properties = default_props.deep_merge(props)
|
97
|
-
# The key is to use update_properties to update the current resource and maintain
|
98
|
-
# the added properties from the convenience methods like scope and description.
|
99
|
-
# At the same time, we do not register the task to all_tasks to avoid creating a Lambda function.
|
65
|
+
# The key to not register the task to all_tasks to avoid creating a Lambda function.
|
100
66
|
# Instead we store it in all_managed_rules.
|
101
|
-
|
102
|
-
definition = @resources.first
|
103
|
-
|
104
|
-
register_managed_rule(name, definition)
|
67
|
+
register_managed_rule(name, managed_rule.definition)
|
105
68
|
end
|
106
69
|
|
107
70
|
# Creates a task but registers it to all_managed_rules instead of all_tasks
|
108
71
|
# because we do not want Lambda functions to be created.
|
109
72
|
def register_managed_rule(name, definition)
|
110
|
-
# A task object is needed to build {namespace} for later replacing.
|
111
|
-
task = Jets::Lambda::Task.new(self.name, name, resources: @resources)
|
112
73
|
|
113
|
-
#
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
74
|
+
# Mimic task to grab base_replacements, namely namespace.
|
75
|
+
# Do not actually use the task to create a Lambda function for managed rules.
|
76
|
+
# Only using the task for base_replacements.
|
77
|
+
resources = [definition]
|
78
|
+
meth = name
|
79
|
+
task = Jets::Lambda::Task.new(self.name, meth,
|
80
|
+
resources: resources,
|
81
|
+
replacements: replacements(meth))
|
82
|
+
all_managed_rules[name] = { definition: definition, replacements: task.replacements }
|
119
83
|
clear_properties
|
120
84
|
end
|
121
85
|
|
86
|
+
# Override lambda/dsl.rb to add config_rule_name also
|
87
|
+
def replacements(meth)
|
88
|
+
name_without_rule = self.name.underscore.gsub(/_rule$/,'')
|
89
|
+
config_rule_name = "#{name_without_rule}_#{meth}".dasherize
|
90
|
+
{
|
91
|
+
config_rule_name: config_rule_name
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
122
95
|
# AWS managed rules are not actual Lambda functions and require their own storage.
|
123
96
|
def all_managed_rules
|
124
97
|
@all_managed_rules ||= ActiveSupport::OrderedHash.new
|
@@ -128,7 +101,7 @@ module Jets::Rule::Dsl
|
|
128
101
|
all_managed_rules.values
|
129
102
|
end
|
130
103
|
|
131
|
-
# Override Lambda::Dsl.build? to account
|
104
|
+
# Override Lambda::Dsl.build? to account for possible managed_rules
|
132
105
|
def build?
|
133
106
|
!tasks.empty? || !managed_rules.empty?
|
134
107
|
end
|
data/lib/jets/stack.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module Jets
|
4
|
+
class Stack
|
5
|
+
autoload :Definition, 'jets/stack/definition' # Registration and definitions
|
6
|
+
autoload :Main, 'jets/stack/main'
|
7
|
+
autoload :Parameter, 'jets/stack/parameter'
|
8
|
+
autoload :Output, 'jets/stack/output'
|
9
|
+
autoload :Resource, 'jets/stack/resource'
|
10
|
+
autoload :Builder, 'jets/stack/builder'
|
11
|
+
autoload :Function, 'jets/stack/function'
|
12
|
+
|
13
|
+
include Main::Dsl
|
14
|
+
include Parameter::Dsl
|
15
|
+
include Output::Dsl
|
16
|
+
include Resource::Dsl
|
17
|
+
|
18
|
+
class << self
|
19
|
+
extend Memoist
|
20
|
+
|
21
|
+
# Track all command subclasses.
|
22
|
+
def subclasses
|
23
|
+
@subclasses ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def inherited(base)
|
27
|
+
super
|
28
|
+
self.subclasses << base if base.name
|
29
|
+
end
|
30
|
+
|
31
|
+
# Build it to figure out if we need to build the stack for the SharedBuilder
|
32
|
+
def build?
|
33
|
+
empty = template == {"Parameters"=>{"IamRole"=>{"Type"=>"String"}, "S3Bucket"=>{"Type"=>"String"}}}
|
34
|
+
!empty
|
35
|
+
end
|
36
|
+
|
37
|
+
def functions
|
38
|
+
stack = new
|
39
|
+
# All the & because resources might be nil
|
40
|
+
templates = stack.resources&.map(&:template)&.select do |t|
|
41
|
+
attributes = t.values.first
|
42
|
+
attributes['Type'] == 'AWS::Lambda::Function'
|
43
|
+
end
|
44
|
+
templates ||= []
|
45
|
+
templates.map { |t| Function.new(t) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def template
|
49
|
+
# Pretty funny looking, creating an instance of stack to be passed to the Builder.
|
50
|
+
# Another way of looking at it:
|
51
|
+
#
|
52
|
+
# stack = new # MyStack.new
|
53
|
+
# builder = Jets::Stack::Builder.new(stack)
|
54
|
+
#
|
55
|
+
builder = Jets::Stack::Builder.new(new)
|
56
|
+
builder.template
|
57
|
+
end
|
58
|
+
memoize :template
|
59
|
+
|
60
|
+
def has_resources?
|
61
|
+
!subclasses.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
# Usage:
|
65
|
+
#
|
66
|
+
# Jets::Stack.has_resources?
|
67
|
+
#
|
68
|
+
def has_resources?
|
69
|
+
# need to eager load the app/shared resources in order to check if shared resources have been registered
|
70
|
+
eager_load_shared_resources!
|
71
|
+
!!subclasses.detect do |subclass|
|
72
|
+
subclass.build?
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def eager_load_shared_resources!
|
77
|
+
ActiveSupport::Dependencies.autoload_paths += ["#{Jets.root}app/shared/resources"]
|
78
|
+
Dir.glob("#{Jets.root}app/shared/resources/*.rb").select do |path|
|
79
|
+
next if !File.file?(path) or path =~ %r{/javascript/} or path =~ %r{/views/}
|
80
|
+
|
81
|
+
class_name = path
|
82
|
+
.sub(/\.rb$/,'') # remove .rb
|
83
|
+
.sub(Jets.root.to_s,'') # remove ./
|
84
|
+
.sub(%r{app/shared/resources/},'') # remove app/shared/resources/
|
85
|
+
.classify
|
86
|
+
class_name.constantize # use constantize instead of require so dont have to worry about order.
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def lookup(logical_id)
|
91
|
+
looker.output(logical_id)
|
92
|
+
end
|
93
|
+
|
94
|
+
def looker
|
95
|
+
Jets::Stack::Output::Lookup.new(self)
|
96
|
+
end
|
97
|
+
memoize :looker
|
98
|
+
|
99
|
+
def output_keys
|
100
|
+
outputs = new.outputs || []
|
101
|
+
outputs.map(&:template).map {|o| o.keys.first}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|