Module: Jets::Lambda::Dsl::ClassMethods

Extended by:
Memoist
Defined in:
lib/jets/lambda/dsl.rb

Constant Summary collapse

PROPERTIES =

Convenience method that set properties. List based on amzn.to/2oSph1P Not all properites are included because some properties are not meant to be set directly. For example, function_name is a calculated setting by Jets.

%W[
  dead_letter_config
  description
  ephemeral_storage
  handler
  kms_key_arn
  logging_config
  memory_size
  reserved_concurrent_executions
  role
  runtime
  tags
  timeout
  tracing_config
  vpc_config
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#provisioned_concurrency=(value) ⇒ Object (writeonly)

Sets the attribute provisioned_concurrency

Parameters:

  • value

    the value to set the attribute provisioned_concurrency to.



107
108
109
# File 'lib/jets/lambda/dsl.rb', line 107

def provisioned_concurrency=(value)
  @provisioned_concurrency = value
end

Class Method Details

.define_associated_properties(associated_properties) ⇒ Object

meta definition



195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/jets/lambda/dsl.rb', line 195

def self.define_associated_properties(associated_properties)
  associated_properties.each do |property|
    # Example:
    #   def config_rule_name(value)
    #     associated_properties(config_rule_name: value)
    #   end
    class_eval "      def \#{property}(value)\n        associated_properties(\#{property}: value)\n      end\n    CODE\n  end\nend\n", __FILE__, __LINE__ + 1

Instance Method Details

#add_logical_id_counterObject

Loop back through the resources and add a counter to the end of the id to handle multiple events. Then replace @associated_resources entirely



220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/jets/lambda/dsl.rb', line 220

def add_logical_id_counter
  numbered_resources = []
  n = 1
  @associated_resources.map do |associated|
    logical_id = associated.logical_id
    attributes = associated.attributes

    logical_id = logical_id.to_s.sub(/\d+$/, "")
    new_definition = {"#{logical_id}#{n}" => attributes}
    numbered_resources << Jets::Cfn::Resource::Associated.new(new_definition)
    n += 1
  end
  @associated_resources = numbered_resources
end

#add_logical_id_counter?Boolean

Returns:

  • (Boolean)


209
210
211
212
213
214
215
# File 'lib/jets/lambda/dsl.rb', line 209

def add_logical_id_counter?
  return false unless @associated_resources
  # Only takes one associated resource with multiple set to true to return false of this check
  return false if @associated_resources.detect { |associated| associated.multiple_resources }
  # Otherwise check if there is more than 1 @associated_resources
  @associated_resources.size > 1
end

#all_private_definitionsObject



380
381
382
# File 'lib/jets/lambda/dsl.rb', line 380

def all_private_definitions
  find_all_definitions(public: false)
end

#all_public_definitionsObject



376
377
378
# File 'lib/jets/lambda/dsl.rb', line 376

def all_public_definitions
  find_all_definitions(public: true)
end

#associated_properties(options = {}) ⇒ Object Also known as: associated_props

Properties belonging to the associated resource



188
189
190
191
# File 'lib/jets/lambda/dsl.rb', line 188

def associated_properties(options = {})
  @associated_properties ||= {}
  @associated_properties.deep_merge!(options)
end

#associated_resources(*definitions) ⇒ Object Also known as: associated_resource, resource

Main method that registers resources associated with the Lambda function. All resources methods lead here.



156
157
158
159
160
161
162
163
164
165
166
# File 'lib/jets/lambda/dsl.rb', line 156

def associated_resources(*definitions)
  if definitions == [nil] # when associated_resources called with no arguments
    @associated_resources || []
  else
    @associated_resources ||= []
    associated_resource = Jets::Cfn::Resource::Associated.new(definitions)
    associated_resource.multiple_resources = @multiple_resources
    @associated_resources << associated_resource
    @associated_resources.flatten!
  end
end

#build?Boolean

Used in Jets::Cfn::Builder::Interface#build Overridden in rule/dsl.rb

Returns:

  • (Boolean)


404
405
406
# File 'lib/jets/lambda/dsl.rb', line 404

def build?
  !definitions.empty?
end

#build_class_iam?Boolean

Returns:

  • (Boolean)


149
150
151
# File 'lib/jets/lambda/dsl.rb', line 149

def build_class_iam?
  !!(class_iam_policy || class_managed_iam_policy)
end

#class_environment(hash) ⇒ Object Also known as: class_env



33
34
35
36
# File 'lib/jets/lambda/dsl.rb', line 33

def class_environment(hash)
  environment = standardize_env(hash)
  class_properties(Environment: environment)
end

#class_iam_policy(*definitions) ⇒ Object

definitions: one or more definitions



120
121
122
123
124
125
126
127
# File 'lib/jets/lambda/dsl.rb', line 120

def class_iam_policy(*definitions)
  if definitions.empty?
    @class_iam_policy
  else
    @class_iam_policy ||= []
    @class_iam_policy += definitions.flatten
  end
end

#class_managed_iam_policy(*definitions) ⇒ Object

definitions: one or more definitions



140
141
142
143
144
145
146
147
# File 'lib/jets/lambda/dsl.rb', line 140

def class_managed_iam_policy(*definitions)
  if definitions.empty?
    @class_managed_iam_policy
  else
    @class_managed_iam_policy ||= []
    @class_managed_iam_policy += definitions.flatten
  end
end

#class_properties(options = nil) ⇒ Object Also known as: class_props



17
18
19
20
21
22
23
24
# File 'lib/jets/lambda/dsl.rb', line 17

def class_properties(options = nil)
  if options
    @class_properties ||= {}
    @class_properties.deep_merge!(options)
  else
    @class_properties || {}
  end
end

#clear_propertiesObject



306
307
308
309
310
311
312
313
# File 'lib/jets/lambda/dsl.rb', line 306

def clear_properties
  @properties = nil
  @provisioned_concurrency = nil
  @iam_policy = nil
  @managed_iam_policy = nil
  @associated_resources = nil
  @associated_properties = nil
end

#definitionsObject

Returns the definitions for this class in Array form.

Returns

Array of definition objects



389
390
391
# File 'lib/jets/lambda/dsl.rb', line 389

def definitions
  all_public_definitions.values
end

#defpoly(lang, meth) ⇒ Object

Polymorphic support



409
410
411
# File 'lib/jets/lambda/dsl.rb', line 409

def defpoly(lang, meth)
  register_definition(meth, lang)
end

#depends_on(*stacks) ⇒ Object

Examples:

depends_on :custom
depends_on :custom, :alert
depends_on :custom, class_prefix: true
depends_on :custom, :alert, class_prefix: true

interface method



243
244
# File 'lib/jets/lambda/dsl.rb', line 243

def depends_on(*stacks)
end

#environment(hash) ⇒ Object Also known as: env



39
40
41
42
# File 'lib/jets/lambda/dsl.rb', line 39

def environment(hash)
  environment = standardize_env(hash)
  properties(Environment: environment)
end

#find_all_definitions(options = {}) ⇒ Object

Goes up the class inheritance chain to build the definitions.

Example heirarchy:

Jets::Lambda::Functions > Jets::Controller::Base > ApplicationController ...
  > PostsController > ChildPostsController

Do not include definitions from the direct subclasses of Jets::Lambda::Functions because those classes are abstract. Dont want those methods to be included.



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/jets/lambda/dsl.rb', line 336

def find_all_definitions(options = {})
  public = options[:public].nil? ? true : options[:public]
  klass = self
  direct_subclasses = Jets::Lambda::Functions.subclasses
  lookup = []

  # Go up class inheritance and builds lookup structure in memory
  until direct_subclasses.include?(klass)
    lookup << klass.send(:all_definitions) # one place we want to call private all_definitions method
    klass = klass.superclass
  end
  merged_definitions = ActiveSupport::OrderedHash.new
  # Go back down the class inheritance chain in reverse order and merge the definitions
  lookup.reverse_each do |definitions_hash|
    # definitions_hash is a result of all_definitions. Example: PostsController.all_definitions
    merged_definitions.merge!(definitions_hash)
  end

  # The cfn builders required the right final child class to build the lambda functions correctly.
  merged_definitions.each do |meth, definition|
    # Override the class name for the cfn builders
    definition = definition.clone # do not stomp over current definitions since things are usually looked by reference
    definition.instance_variable_set(:@class_name, name)
    merged_definitions[meth] = definition
  end

  # Methods can be made private with the :private keyword after the method has been defined.
  # To account for this, loop back thorugh all the methods and check if the method is indeed public.
  definitions = ActiveSupport::OrderedHash.new
  merged_definitions.each do |meth, definition|
    if public
      definitions[meth] = definition if definition.public_meth?
    else
      definitions[meth] = definition unless definition.public_meth?
    end
  end
  definitions
end

#iam_policy(*definitions) ⇒ Object

definitions: one or more definitions



110
111
112
113
114
115
116
117
# File 'lib/jets/lambda/dsl.rb', line 110

def iam_policy(*definitions)
  if definitions.empty?
    @iam_policy
  else
    @iam_policy ||= []
    @iam_policy += definitions.flatten
  end
end

#lambda_functionsObject

The public methods defined in the project app class ulimately become lambda functions.

Example return value:

[:index, :new, :create, :show]


398
399
400
# File 'lib/jets/lambda/dsl.rb', line 398

def lambda_functions
  all_public_definitions.keys
end

#managed_iam_policy(*definitions) ⇒ Object

definitions: one or more definitions



130
131
132
133
134
135
136
137
# File 'lib/jets/lambda/dsl.rb', line 130

def managed_iam_policy(*definitions)
  if definitions.empty?
    @managed_iam_policy
  else
    @managed_iam_policy ||= []
    @managed_iam_policy += definitions.flatten
  end
end

#method_added(meth) ⇒ Object

meth is a Symbol



255
256
257
258
259
260
# File 'lib/jets/lambda/dsl.rb', line 255

def method_added(meth)
  return if %w[initialize method_missing].include?(meth.to_s)
  return unless public_method_defined?(meth)

  register_definition(meth)
end

#node(meth) ⇒ Object



417
418
419
# File 'lib/jets/lambda/dsl.rb', line 417

def node(meth)
  defpoly(:node, meth)
end

#properties(options = {}) ⇒ Object Also known as: props



27
28
29
30
# File 'lib/jets/lambda/dsl.rb', line 27

def properties(options = {})
  @properties ||= {}
  @properties.deep_merge!(options)
end

#properties_listObject

Expose the PROPERTIES list so we can access it



95
96
97
# File 'lib/jets/lambda/dsl.rb', line 95

def properties_list
  PROPERTIES
end

#python(meth) ⇒ Object



413
414
415
# File 'lib/jets/lambda/dsl.rb', line 413

def python(meth)
  defpoly(:python, meth)
end

#ref(name) ⇒ Object



246
247
248
# File 'lib/jets/lambda/dsl.rb', line 246

def ref(name)
  "!Ref #{name.to_s.camelize}"
end

#register_definition(meth, lang = :ruby) ⇒ Object



262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/jets/lambda/dsl.rb', line 262

def register_definition(meth, lang = :ruby)
  # Note: for anonymous classes like for app/functions self.name is ""
  # We adjust the class name when we build the functions later in
  # FunctionContstructor#adjust_definitions.

  # At this point we can use the current associated_properties and defined the
  # associated resource with the Lambda function.
  unless associated_properties.empty?
    associated_resources(default_associated_resource_definition(meth))
  end

  # Unsure why but we have to use @associated_resources vs associated_resources
  # associated_resources is always nil
  if add_logical_id_counter?
    add_logical_id_counter
  end

  all_definitions[meth] = Jets::Lambda::Definition.new(name, meth,
    properties: @properties, # lambda function properties
    provisioned_concurrency: @provisioned_concurrency,
    iam_policy: @iam_policy,
    managed_iam_policy: @managed_iam_policy,
    associated_resources: @associated_resources,
    lang: lang,
    replacements: replacements(meth))

  # Done storing options, clear out for the next added method.
  clear_properties
  # Important to clear @properties at the end of registering outside of
  # register_definition because register_definition is overridden in Jets::Event::Dsl
  #
  #   Jets::Event::Base < Jets::Lambda::Functions
  #
  # Both Jets::Event::Base and Jets::Lambda::Functions have Dsl modules included.
  # So the Jets::Event::Dsl overrides some of the Jets::Lambda::Dsl behavior.

  true
end

#replacements(meth) ⇒ Object

Meant to be overridden to add more custom replacements based on the app class type



302
303
304
# File 'lib/jets/lambda/dsl.rb', line 302

def replacements(meth)
  {}
end

#standardize_env(hash) ⇒ Object

Allows user to pass in hash with or without the :variables key.



46
47
48
49
50
51
52
53
# File 'lib/jets/lambda/dsl.rb', line 46

def standardize_env(hash)
  return hash if hash.key?(:Variables)

  environment = {}
  environment[:Variables] ||= {}
  environment[:Variables].merge!(hash)
  environment
end

#sub(value) ⇒ Object



250
251
252
# File 'lib/jets/lambda/dsl.rb', line 250

def sub(value)
  "!Sub #{value.to_s.camelize}"
end

#with_fresh_properties(fresh_properties: true, multiple_resources: true) ⇒ Object

Using this odd way of setting these properties so we can keep the resource(*definitions) signature simple. Using keyword arguments at the end interfere with being able to pass in any keys for the properties hash at the end.

TODO: If there’s a cleaner way of doing this, let me know.



177
178
179
180
181
182
183
184
185
# File 'lib/jets/lambda/dsl.rb', line 177

def with_fresh_properties(fresh_properties: true, multiple_resources: true)
  @associated_properties = nil if fresh_properties # dont use any current associated_properties
  @multiple_resources = multiple_resources

  yield

  @multiple_resources = false
  @associated_properties = nil if fresh_properties # reset for next definition, since we're defining eagerly
end