class Cfhighlander::Compiler::LambdaResolver
Public Class Methods
new(component, lambda_key, workdir, confirm_code_execution = true, mock_resolve=false)
click to toggle source
# File lib/cfhighlander.compiler.rb, line 237 def initialize(component, lambda_key, workdir, confirm_code_execution = true, mock_resolve=false) @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 @mock_resolve = mock_resolve end
Public Instance Methods
generateMockArchives()
click to toggle source
# File lib/cfhighlander.compiler.rb, line 402 def generateMockArchives @lambda_config['functions'].each do |name, _| @metadata['sha256'][name] = 'mockSHA' @metadata['version'][name] = 'mockVersion' end return [] end
generateSourceArchives()
click to toggle source
# File lib/cfhighlander.compiler.rb, line 252 def generateSourceArchives return generateMockArchives if @mock_resolve 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 "INFO | Lambda #{name} | Start package process" puts "INFO | Lambda #{name} | Destination is #{full_destination_path}" md5 = Digest::MD5.new md5.update lambda_config['code'] hash = md5.hexdigest cached_location = "#{ENV['HOME']}/.cfhighlander/cache/lambdas/#{hash}" if cached_downloads.key? lambda_config['code'] puts "INFO | Lambda #{name} | Using already downloaded archive #{lambda_config['code']}" FileUtils.copy(cached_downloads[lambda_config['code']], full_destination_path) elsif File.file? cached_location puts "INFO | Lambda #{name} | Using cache from #{cached_location}" FileUtils.copy(cached_location, full_destination_path) else if lambda_config['code'].include? 'http' puts "INFO | Lambda #{name} | Downloading source from #{lambda_config['code']}" download = open(lambda_config['code']) IO.copy_stream(download, "#{out_folder}/src.zip") FileUtils.mkdir_p("#{ENV['HOME']}/.cfhighlander/cache/lambdas") FileUtils.copy("#{out_folder}/src.zip", cached_location) FileUtils.copy("#{out_folder}/src.zip", full_destination_path) puts "INFO | Lambda #{name} | source cached to #{cached_location}" cached_downloads[lambda_config['code']] = cached_location elsif lambda_config['code'].include? 's3://' parts = lambda_config['code'].split('/') if parts.size < 4 STDERR.puts "ERROR | Lambda #{name} | Lambda function source code from s3 should be in s3://bucket/path format" exit -8 end bucket = parts[2] key = parts.drop(3).join('/') s3 = Aws::S3::Client.new({ region: s3_bucket_region(bucket) }) puts "INFO | Lambda #{name} | Downloading source from #{lambda_config['code']}" s3.get_object({ bucket: bucket, key: key, response_target: cached_location }) puts "INFO | Lambda #{name} | source cached to #{cached_location}" FileUtils.copy(cached_location, full_destination_path) cached_downloads[lambda_config['code']] = cached_location else # zip local code component = @component component_dir = component.template.template_location full_path_candidate_1 = "#{component_dir}/lambdas/#{lambda_config['code']}" full_path_candidate_2 = "#{component_dir}/#{lambda_config['code']}" full_path_candidate_3 = lambda_config['code'] full_path = full_path_candidate_1 full_path = full_path_candidate_2 if (File.exist? full_path_candidate_2 and (not File.exist? full_path)) full_path = full_path_candidate_3 if (File.exist? full_path_candidate_3 and (not File.exist? full_path)) # if component extends another component, both parent and child paths should be taken in # consideration 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_candidate_1 = "#{component_dir}/lambdas/#{lambda_config['code']}" if parent_exists full_path_candidate_2 = "#{component_dir}/#{lambda_config['code']}" if parent_exists full_path_candidate_3 = "#{lambda_config['code']}" if parent_exists full_path = full_path_candidate_1 full_path = full_path_candidate_2 if (File.exist? full_path_candidate_2 and (not File.exist? full_path)) full_path = full_path_candidate_3 if (File.exist? full_path_candidate_3 and (not File.exist? full_path)) component_dir = nil unless parent_exists end if component_dir.nil? STDERR.puts "ERROR | Lambda #{name} | Could not find source code directory 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 "INFO | Lambda #{name} | 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 | Lambda #{name} | create package - following command failed\n\n#{package_cmd}\n\n" exit -4 end end File.delete full_destination_path if File.exist? full_destination_path # if source is already zip file, just add manifest to it if full_path.end_with? '.zip' FileUtils.copy full_path, full_destination_path else zip_generator = Cfhighlander::Util::ZipFileGenerator.new(lambda_source_dir, full_destination_path) zip_generator.write end end 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 "INFO | Lambda #{name} | Created zip package #{full_destination_path} with digest #{sha256}" @metadata['sha256'][name] = sha256 @metadata['version'][name] = timestamp end if ((not @lambda_config.nil?) and @lambda_config.key? 'functions') return archive_paths end
mergeComponentConfig()
click to toggle source
# File lib/cfhighlander.compiler.rb, line 410 def mergeComponentConfig if @component.config.key? 'lambda_metadata' @metadata.each do |mk, mh| mh.each do |k, v| @component.config['lambda_metadata'][mk][k] = v end end else @component.config['lambda_metadata'] = @metadata end end