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



200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/jets/lambda/dsl.rb', line 200

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 <<~CODE, __FILE__, __LINE__ + 1
      def #{property}(value)
        associated_properties(#{property}: value)
      end
    CODE
  end
end

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



225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/jets/lambda/dsl.rb', line 225

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)


214
215
216
217
218
219
220
# File 'lib/jets/lambda/dsl.rb', line 214

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



386
387
388
# File 'lib/jets/lambda/dsl.rb', line 386

def all_private_definitions
  find_all_definitions(public: false)
end

#all_public_definitionsObject



382
383
384
# File 'lib/jets/lambda/dsl.rb', line 382

def all_public_definitions
  find_all_definitions(public: true)
end

#associated_outputs(outputs = {}) ⇒ Object



172
173
174
175
# File 'lib/jets/lambda/dsl.rb', line 172

def associated_outputs(outputs = {})
  @associated_outputs ||= []
  @associated_outputs << outputs
end

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

Properties belonging to the associated resource



193
194
195
196
# File 'lib/jets/lambda/dsl.rb', line 193

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)


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

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



312
313
314
315
316
317
318
319
# File 'lib/jets/lambda/dsl.rb', line 312

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



395
396
397
# File 'lib/jets/lambda/dsl.rb', line 395

def definitions
  all_public_definitions.values
end

#defpoly(lang, meth) ⇒ Object

Polymorphic support



415
416
417
# File 'lib/jets/lambda/dsl.rb', line 415

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



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

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.



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
374
375
376
377
378
379
# File 'lib/jets/lambda/dsl.rb', line 342

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]


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

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



260
261
262
263
264
265
# File 'lib/jets/lambda/dsl.rb', line 260

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



423
424
425
# File 'lib/jets/lambda/dsl.rb', line 423

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



419
420
421
# File 'lib/jets/lambda/dsl.rb', line 419

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

#ref(name) ⇒ Object



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

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

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



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
300
301
302
303
304
305
# File 'lib/jets/lambda/dsl.rb', line 267

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,
    associated_outputs: @associated_outputs,
    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



308
309
310
# File 'lib/jets/lambda/dsl.rb', line 308

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



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

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.



182
183
184
185
186
187
188
189
190
# File 'lib/jets/lambda/dsl.rb', line 182

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