Class: Cfhighlander::Compiler::LambdaResolver

Inherits:
Object
  • Object
show all
Defined in:
lib/cfhighlander.compiler.rb

Instance Method Summary collapse

Constructor Details

#initialize(component, lambda_key, workdir, confirm_code_execution = true) ⇒ LambdaResolver

Returns a new instance of LambdaResolver.



206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/cfhighlander.compiler.rb', line 206

def initialize(component, lambda_key, workdir, confirm_code_execution = true)
  @component = component
  @lambda_config = @component.config[lambda_key]
  @component_dir = @component.component_dir
  @workdir = workdir
  @metadata = {
      'path' => {},
      'sha256' => {},
      'version' => {}
  }
  @confirm_code_execution = confirm_code_execution
end

Instance Method Details

#generateSourceArchives ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
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
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/cfhighlander.compiler.rb', line 219

def generateSourceArchives

  # Clear previous packages
  FileUtils.rmtree "#{@workdir}/output/lambdas"

  archive_paths = []

  # Cached downloads map
  cached_downloads = {}
  @lambda_config['functions'].each do |name, lambda_config|
    # create folder
    out_folder = "#{@workdir}/out/lambdas/"
    timestamp = Time.now.utc.to_i.to_s
    file_name = "#{name}.#{@component.name}.#{@component.version}.#{timestamp}.zip"
    @metadata['path'][name] = file_name
    full_destination_path = "#{out_folder}#{file_name}"
    info_path = "#{out_folder}#{file_name}.info.yaml"
    archive_paths << full_destination_path
    FileUtils.mkdir_p out_folder
    File.write(info_path, {
        'component' => @component.name,
        'function' => name,
        'packagedAt' => timestamp,
        'config' => lambda_config
    }.to_yaml)

    # clear destination if already there
    FileUtils.remove full_destination_path if File.exist? full_destination_path

    # download file if code remote archive
    puts "Packaging AWS Lambda function #{name}...\n"
    puts "Destination archive is #{full_destination_path}"
    if lambda_config['code'].include? 'http'
      md5 = Digest::MD5.new
      md5.update lambda_config['code']
      hash = md5.hexdigest
      cached_location = "#{@workdir}/.cache/lambdas/#{hash}"
      if cached_downloads.key? lambda_config['code']
        puts "Using already downloaded archive #{lambda_config['code']}"
        FileUtils.copy(cached_downloads[lambda_config['code']], full_destination_path)
      elsif File.file? cached_location
        puts "Using cached download - '#{cached_location}'"
        FileUtils.copy(cached_location, full_destination_path)
      else
        puts "Downloading file #{lambda_config['code']} ..."
        download = open(lambda_config['code'])
        IO.copy_stream(download, "#{out_folder}/src.zip")
        FileUtils.mkdir_p('.cache/lambdas')
        FileUtils.copy("#{out_folder}/src.zip", cached_location)
        FileUtils.copy("#{out_folder}/src.zip", full_destination_path)
        puts "Download complete, caching in #{cached_location}"
        cached_downloads[lambda_config['code']] = cached_location
      end
    else
      # zip local code
      component = @component
      component_dir = component.template.template_location
      full_path = "#{component_dir}/lambdas/#{lambda_config['code']}"

      until (File.exist? full_path or component_dir.nil?)
        parent_exists = (not component.extended_component.nil?)
        component = component.extended_component if parent_exists
        component_dir = component.template.template_location if parent_exists
        full_path = "#{component_dir}/lambdas/#{lambda_config['code']}" if parent_exists
        component_dir = nil unless parent_exists
      end
      if component_dir.nil?
        STDERR.puts "ERROR: Could not find source code directory for lambda function #{name} in component #{@component.name}"
        exit -9
      end

      # lambda source can be either path to file or directory within that file
      # optionally, lambda source code
      lambda_source_dir = File.dirname(full_path)
      lambda_source_dir = full_path if Pathname.new(full_path).directory?

      # executing package command can generate files. We DO NOT want this file in source directory,
      # but rather in intermediate directory
      tmp_source_dir = "#{@workdir}/out/lambdas/tmp/#{name}"
      FileUtils.rmtree(File.dirname(tmp_source_dir)) if File.exist? tmp_source_dir
      FileUtils.mkpath(File.dirname(tmp_source_dir))
      FileUtils.copy_entry(lambda_source_dir, tmp_source_dir)
      lambda_source_dir = tmp_source_dir

      # Lambda function source code allows pre-processing (e.g. install code dependencies)
      unless lambda_config['package_cmd'].nil?
        puts "Following code will be executed to generate lambda function #{name}:\n\n#{lambda_config['package_cmd']}\n\n"

        if @confirm_code_execution
          exit -7 unless HighLine.agree('Proceed (y/n)?')
        end

        package_cmd = "cd #{lambda_source_dir} && #{lambda_config['package_cmd']}"
        puts 'Processing package command...'
        package_result = system(package_cmd)
        unless package_result
          puts "Error packaging lambda function, following command failed\n\n#{package_cmd}\n\n"
          exit -4
        end
      end
      File.delete full_destination_path if File.exist? full_destination_path
      zip_generator = Cfhighlander::Util::ZipFileGenerator.new(lambda_source_dir, full_destination_path)
      zip_generator.write

    end
    # add version information to avoid same package ever deployed 2 times
    Zip::File.open(full_destination_path) do |zipfile|
      zipfile.add 'hlpackage_info.txt', info_path
    end
    sha256 = Digest::SHA256.file full_destination_path
    sha256 = sha256.base64digest
    puts "Created zip package #{full_destination_path} for lambda #{name} with digest #{sha256}"
    @metadata['sha256'][name] = sha256
    @metadata['version'][name] = timestamp
  end

  return archive_paths
end

#mergeComponentConfig ⇒ Object



338
339
340
# File 'lib/cfhighlander.compiler.rb', line 338

def mergeComponentConfig
  @component.config['lambda_metadata'] = @metadata
end