Class: Jets::Resource::Lambda::Function

Inherits:
Base
  • Object
show all
Includes:
Environment
Defined in:
lib/jets/resource/lambda/function.rb,
lib/jets/resource/lambda/function/environment.rb

Defined Under Namespace

Modules: Environment

Instance Method Summary collapse

Methods included from Environment

#env_properties, #environment, #jets_env

Methods inherited from Base

#resource

Constructor Details

#initialize(task) ⇒ Function

Returns a new instance of Function.



5
6
7
8
# File 'lib/jets/resource/lambda/function.rb', line 5

def initialize(task)
  @task = task
  @app_class = task.class_name.to_s
end

Instance Method Details

#class_propertiesObject

Class properties example:

class PostsController < ApplicationController
  class_timeout 22
  ...
end

Also handles iam policy override at the class level. Example:

class_iam_policy("logs:*")


70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/jets/resource/lambda/function.rb', line 70

def class_properties
  # klass is PostsController, HardJob, GameRule, Hello or HelloFunction
  klass = Jets::Klass.from_task(@task)

  class_properties = lookup_class_properties(klass)
  if klass.build_class_iam?
    iam_policy = Jets::Resource::Iam::ClassRole.new(klass)
    class_properties[:role] = "!GetAtt #{iam_policy.logical_id}.Arn"
  end

  class_properties
end

#code_s3_keyObject



184
185
186
187
# File 'lib/jets/resource/lambda/function.rb', line 184

def code_s3_key
  checksum = Jets::Builders::Md5.checksums["stage/code"]
  "jets/code/code-#{checksum}.zip" # s3_key
end

#combined_propertiesObject



27
28
29
30
31
32
33
# File 'lib/jets/resource/lambda/function.rb', line 27

def combined_properties
  props = env_properties
    .deep_merge(global_properties)
    .deep_merge(class_properties)
    .deep_merge(function_properties)
  finalize_properties!(props)
end

#default_handlerObject



157
158
159
160
161
162
163
164
# File 'lib/jets/resource/lambda/function.rb', line 157

def default_handler
  map = {
    node: @task.full_handler(:handler), # IE: handlers/controllers/posts/show.handler
    python: @task.full_handler(:lambda_handler), # IE: handlers/controllers/posts/show.lambda_handler
    ruby: handler, # IE: handlers/controllers/posts_controllers.index
  }
  map[@task.lang]
end

#default_runtimeObject



148
149
150
151
152
153
154
155
# File 'lib/jets/resource/lambda/function.rb', line 148

def default_runtime
  map = {
    node: "nodejs8.10",
    python: "python3.6",
    ruby: Jets.ruby_runtime,
  }
  map[@task.lang]
end

#definitionObject



10
11
12
13
14
15
16
17
# File 'lib/jets/resource/lambda/function.rb', line 10

def definition
  {
    function_logical_id => {
      type: "AWS::Lambda::Function",
      properties: combined_properties
    }
  }
end

#descriptionObject



207
208
209
210
211
212
213
214
# File 'lib/jets/resource/lambda/function.rb', line 207

def description
  # Example values:
  #   @app_class: Admin/PagesController
  #   @task.meth: index
  # Returns:
  #   Admin/PagesController#index
  "#{@app_class}##{@task.meth}"
end

#finalize_properties!(props) ⇒ Object

Properties managed by Jets with merged with finality.



123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/jets/resource/lambda/function.rb', line 123

def finalize_properties!(props)
  handler = full_handler(props)
  runtime = get_runtime(props)
  managed = {
    handler: handler,
    runtime: runtime,
    description: description,
  }
  managed[:function_name] = function_name if function_name
  layers = get_layers(runtime)
  managed[:layers] = layers if layers
  props.merge!(managed)
end

#full_handler(props) ⇒ Object

Ensure that the handler path is normalized.



176
177
178
179
180
181
182
# File 'lib/jets/resource/lambda/function.rb', line 176

def full_handler(props)
  if props[:handler]
    handler_value(props[:handler])
  else
    default_handler
  end
end

#function_logical_idObject



19
20
21
# File 'lib/jets/resource/lambda/function.rb', line 19

def function_logical_id
  "{namespace}_lambda_function".underscore
end

#function_nameObject

Examples:

"#{Jets.config.project_namespace}-sleep_job-perform"
"demo-dev-sleep_job-perform"


192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/jets/resource/lambda/function.rb', line 192

def function_name
  # Example values:
  #   @app_class: admin/pages_controller
  #   @task.meth: index
  #   method: admin/pages_controller
  #   method: admin-pages_controller-index
  method = @app_class.underscore
  method = method.gsub('/','-').gsub(/[^0-9a-z\-_]/i, '') + "-#{@task.meth}"
  function_name = "#{Jets.config.project_namespace}-#{method}"
  # Returns nil if function name is too long.
  # CloudFormation will managed the the function name in this case.
  # A pretty function name won't be generated but the deploy will be successful.
  function_name.size > Jets::MAX_FUNCTION_NAME_SIZE ? nil : function_name
end

#function_propertiesObject

Function properties example:

class PostsController < ApplicationController

timeout 18
def index
  ...
end

Also handles iam policy override at the function level. Example:

iam_policy("ec2:*")
def new
  render json: params.merge(action: "new")
end


113
114
115
116
117
118
119
120
# File 'lib/jets/resource/lambda/function.rb', line 113

def function_properties
  properties = @task.properties
  if @task.build_function_iam?
    iam_policy = Jets::Resource::Iam::FunctionRole.new(@task)
    properties[:role] = "!GetAtt #{iam_policy.logical_id}.Arn"
  end
  properties
end

#get_layers(runtime) ⇒ Object



137
138
139
140
141
142
# File 'lib/jets/resource/lambda/function.rb', line 137

def get_layers(runtime)
  return nil unless runtime =~ /^ruby/
  return Jets.config.lambda.layers if Jets.config.gems.disable
  
  ["!Ref GemLayer"] + Jets.config.lambda.layers
end

#get_runtime(props) ⇒ Object



144
145
146
# File 'lib/jets/resource/lambda/function.rb', line 144

def get_runtime(props)
  props[:runtime] || default_runtime
end

#global_propertiesObject

Global properties example: jets defaults are in jets/default/application.rb. Your application’s default config/application.rb then get used. Example:

Jets.application.configure do
  config.function = ActiveSupport::OrderedOptions.new
  config.function.timeout = 30
  config.function.runtime = "nodejs8.10"
  config.function.memory_size = 1536
end


45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/jets/resource/lambda/function.rb', line 45

def global_properties
  baseline = {
    code: {
      s3_bucket: "!Ref S3Bucket",
      s3_key: code_s3_key
    },
    role: "!Ref IamRole",
    environment: { variables: environment },
  }

  application_config = Jets.application.config.function.to_h
  baseline.merge(application_config)
end

#handlerObject



166
167
168
# File 'lib/jets/resource/lambda/function.rb', line 166

def handler
  handler_value(@task.meth)  # IE: handlers/controllers/posts_controllers.index
end

#handler_value(meth) ⇒ Object

Used for node-shim also



171
172
173
# File 'lib/jets/resource/lambda/function.rb', line 171

def handler_value(meth)
  "handlers/#{@task.type.pluralize}/#{@app_class.underscore}.#{meth}"
end

#lookup_class_properties(klass) ⇒ Object

Accounts for inherited class_properties



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/jets/resource/lambda/function.rb', line 84

def lookup_class_properties(klass)
  all_classes = []
  while klass != Object
    all_classes << klass
    klass = klass.superclass
  end
  class_properties = {}
  # Go back down class heirachry top to down
  all_classes.reverse.each do |k|
    class_properties.merge!(k.class_properties)
  end
  class_properties
end

#replacementsObject



23
24
25
# File 'lib/jets/resource/lambda/function.rb', line 23

def replacements
  @task.replacements # has namespace replacement
end