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
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
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
|
# File 'lib/cfhighlander.compiler.rb', line 254
def generateSourceArchives
return generateMockArchives if @mock_resolve
archive_paths = []
cached_downloads = {}
@lambda_config['functions'].each do |name, lambda_config|
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)
FileUtils.remove full_destination_path if File.exist? full_destination_path
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
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))
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_dir = File.dirname(full_path)
lambda_source_dir = full_path if Pathname.new(full_path).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
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 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
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
|