lono 8.0.0.pre.rc1 → 8.0.0.pre.rc4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cody/acceptance/bin/build.sh +5 -5
- data/.github/ISSUE_TEMPLATE/bug_report.md +84 -0
- data/.github/ISSUE_TEMPLATE/documentation.md +12 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +64 -0
- data/.github/ISSUE_TEMPLATE/question.md +14 -0
- data/.github/ISSUE_TEMPLATE.md +7 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +50 -0
- data/CHANGELOG.md +59 -2
- data/Gemfile +1 -3
- data/README.md +2 -7
- data/lib/lono/app/callable_option/concern.rb +12 -0
- data/lib/lono/app/callable_option.rb +56 -0
- data/lib/lono/app.rb +56 -20
- data/lib/lono/autoloader.rb +1 -0
- data/lib/lono/aws_services/helper.rb +0 -2
- data/lib/lono/blueprint.rb +1 -18
- data/lib/lono/builder/allow/base.rb +54 -0
- data/lib/lono/builder/allow/env.rb +17 -0
- data/lib/lono/builder/allow/region.rb +20 -0
- data/lib/lono/builder/allow.rb +8 -0
- data/lib/lono/builder/configset/combiner.rb +145 -0
- data/lib/lono/builder/configset/definition/base.rb +47 -0
- data/lib/lono/builder/configset/definition/context.rb +70 -0
- data/lib/lono/{configset/strategy/helpers/dsl → builder/configset/definition/dsl/syntax}/auth.rb +1 -1
- data/lib/lono/builder/configset/definition/dsl/syntax/content.rb +22 -0
- data/lib/lono/{configset/strategy/helpers/dsl/syntax.rb → builder/configset/definition/dsl/syntax/core.rb} +15 -9
- data/lib/lono/{configset/strategy/helpers/dsl → builder/configset/definition/dsl/syntax}/package.rb +1 -1
- data/lib/lono/builder/configset/definition/dsl/syntax.rb +5 -0
- data/lib/lono/{configset/strategy → builder/configset/definition}/dsl.rb +10 -14
- data/lib/lono/{configset/strategy → builder/configset/definition}/erb.rb +13 -16
- data/lib/lono/builder/configset/definition.rb +18 -0
- data/lib/lono/builder/configset/evaluator.rb +10 -0
- data/lib/lono/builder/configset/registration.rb +35 -0
- data/lib/lono/builder/context.rb +33 -18
- data/lib/lono/builder/dsl/evaluator.rb +45 -0
- data/lib/lono/builder/dsl/finalizer/base.rb +8 -0
- data/lib/lono/builder/dsl/finalizer/configsets.rb +20 -0
- data/lib/lono/builder/dsl/finalizer/files/base.rb +4 -0
- data/lib/lono/builder/dsl/finalizer/files/build.rb +50 -0
- data/lib/lono/builder/dsl/finalizer/files/replace.rb +36 -0
- data/lib/lono/builder/dsl/finalizer/files.rb +9 -0
- data/lib/lono/builder/{template/dsl → dsl}/finalizer/parameter_groups.rb +6 -5
- data/lib/lono/builder/dsl/finalizer.rb +15 -0
- data/lib/lono/builder/{template/dsl/evaluator/helpers/ec2_helper.rb → dsl/helpers/ec2.rb} +3 -3
- data/lib/lono/builder/dsl/helpers/files.rb +7 -0
- data/lib/lono/builder/{template/helpers.rb → dsl/helpers/partials.rb} +48 -57
- data/lib/lono/builder/dsl/helpers/s3.rb +14 -0
- data/lib/lono/builder/{context/ssm_fetcher.rb → dsl/helpers/ssm/fetcher.rb} +5 -3
- data/lib/lono/builder/{context/helpers.rb → dsl/helpers/ssm.rb} +3 -3
- data/lib/lono/builder/{template/dsl/evaluator/helpers/stack_helper.rb → dsl/helpers/stack.rb} +6 -6
- data/lib/lono/builder/{template/dsl/evaluator/helpers/tags_helper.rb → dsl/helpers/tags.rb} +2 -2
- data/lib/lono/builder/dsl/helpers/template_file.rb +66 -0
- data/lib/lono/builder/dsl/helpers.rb +5 -0
- data/lib/lono/builder/{template/dsl/evaluator/section → dsl/syntax/core}/base.rb +4 -5
- data/lib/lono/builder/{template/dsl/evaluator/section → dsl/syntax/core}/condition.rb +1 -1
- data/lib/lono/builder/{template/dsl/evaluator/section → dsl/syntax/core}/mapping.rb +1 -1
- data/lib/lono/builder/{template/dsl/evaluator/section → dsl/syntax/core}/output.rb +1 -1
- data/lib/lono/builder/{template/dsl/evaluator/section → dsl/syntax/core}/parameter.rb +1 -1
- data/lib/lono/builder/{template/dsl/evaluator/section → dsl/syntax/core}/resource/property_mover.rb +12 -2
- data/lib/lono/builder/{template/dsl/evaluator/section → dsl/syntax/core}/resource.rb +1 -1
- data/lib/lono/builder/{template/dsl/evaluator/section → dsl/syntax/core}/section.rb +1 -1
- data/lib/lono/builder/dsl/syntax/core/squeezer.rb +40 -0
- data/lib/lono/builder/{template/dsl/evaluator/section/methods.rb → dsl/syntax/core.rb} +2 -2
- data/lib/lono/builder/{template/dsl/evaluator → dsl/syntax}/fn.rb +1 -3
- data/lib/lono/builder/{template/dsl/evaluator → dsl}/syntax/parameter_group.rb +1 -1
- data/lib/lono/builder/dsl/syntax.rb +9 -0
- data/lib/lono/builder/{template/dsl.rb → dsl.rb} +2 -2
- data/lib/lono/builder/param.rb +5 -2
- data/lib/lono/builder/template/upload.rb +2 -15
- data/lib/lono/builder/template.rb +1 -3
- data/lib/lono/builder/{template/dsl/evaluator → util}/stringify.rb +1 -1
- data/lib/lono/builder.rb +39 -0
- data/lib/lono/bundler/component/props/extension.rb +0 -1
- data/lib/lono/bundler/extract/tar.rb +0 -1
- data/lib/lono/bundler/util/git.rb +18 -16
- data/lib/lono/cfn/base.rb +2 -2
- data/lib/lono/cfn/cancel.rb +5 -5
- data/lib/lono/cfn/concerns/build.rb +1 -1
- data/lib/lono/cfn/delete.rb +5 -2
- data/lib/lono/cfn/deploy/iam.rb +1 -2
- data/lib/lono/cfn/deploy/rollback.rb +1 -3
- data/lib/lono/cfn/deploy.rb +46 -5
- data/lib/lono/cfn/download.rb +0 -1
- data/lib/lono/cfn/plan/changeset.rb +3 -3
- data/lib/lono/cfn/plan/diff/data.rb +11 -1
- data/lib/lono/cfn/plan/diff/file.rb +2 -1
- data/lib/lono/cfn/plan/param.rb +1 -1
- data/lib/lono/cfn/plan/template.rb +2 -2
- data/lib/lono/cfn/plan.rb +1 -0
- data/lib/lono/cli/abstract.rb +0 -6
- data/lib/lono/cli/base.rb +6 -3
- data/lib/lono/cli/clean.rb +3 -2
- data/lib/lono/cli/help/cfn/status.md +0 -1
- data/lib/lono/cli/help/new/helper.md +27 -0
- data/lib/lono/cli/help/new/hook.md +14 -0
- data/lib/lono/cli/help/new/project.md +3 -10
- data/lib/lono/cli/help/seed.md +22 -21
- data/lib/lono/cli/iam.rb +27 -0
- data/lib/lono/cli/list.rb +3 -6
- data/lib/lono/cli/new/blueprint.rb +3 -9
- data/lib/lono/cli/new/configset.rb +11 -44
- data/lib/lono/cli/new/helper.rb +19 -11
- data/lib/lono/cli/new/hook.rb +32 -0
- data/lib/lono/cli/new/sequence.rb +6 -1
- data/lib/lono/cli/new.rb +9 -9
- data/lib/lono/cli/s3.rb +3 -3
- data/lib/lono/cli/script/build.rb +0 -5
- data/lib/lono/cli/status.rb +18 -0
- data/lib/lono/{inspector → cli}/summary.rb +23 -33
- data/lib/lono/cli.rb +16 -16
- data/lib/lono/command.rb +28 -2
- data/lib/lono/component.rb +29 -0
- data/lib/lono/concerns/aws_info.rb +14 -0
- data/lib/lono/concerns/names.rb +9 -0
- data/lib/lono/configset.rb +17 -0
- data/lib/lono/core.rb +11 -1
- data/lib/lono/ext/bundler.rb +7 -0
- data/lib/lono/ext/core/module.rb +31 -0
- data/lib/lono/ext/core/object.rb +32 -0
- data/lib/lono/ext/core/string.rb +9 -0
- data/lib/lono/ext.rb +4 -0
- data/lib/lono/files/base.rb +12 -0
- data/lib/lono/{utils → files/builder/lambda_layer}/rsync.rb +3 -5
- data/lib/lono/{app_file/build → files/builder}/lambda_layer/ruby_packager.rb +104 -79
- data/lib/lono/files/builder/lambda_layer/ruby_version.rb +38 -0
- data/lib/lono/files/builder/lambda_layer.rb +17 -0
- data/lib/lono/files/builder.rb +37 -0
- data/lib/lono/files/compressor.rb +53 -0
- data/lib/lono/files/concerns/post_processing.rb +52 -0
- data/lib/lono/files/concerns/registration.rb +16 -0
- data/lib/lono/files/registry.rb +6 -0
- data/lib/lono/files.rb +41 -0
- data/lib/lono/hooks/builder.rb +50 -0
- data/lib/lono/hooks/concern.rb +9 -0
- data/lib/lono/hooks/dsl.rb +20 -0
- data/lib/lono/hooks/runner.rb +46 -0
- data/lib/lono/layering/layer.rb +64 -56
- data/lib/lono/logger.rb +2 -3
- data/lib/lono/names.rb +7 -10
- data/lib/lono/s3/bucket.rb +43 -37
- data/lib/lono/s3/rollback.rb +8 -0
- data/lib/lono/s3/uploader.rb +33 -28
- data/lib/lono/script/build.rb +0 -5
- data/lib/lono/seeder.rb +38 -29
- data/lib/lono/user_data.rb +3 -1
- data/lib/lono/utils/sh.rb +32 -0
- data/lib/lono/utils.rb +5 -0
- data/lib/lono/version.rb +1 -1
- data/lib/lono/yamler/validator.rb +7 -22
- data/lib/lono.rb +8 -0
- data/lib/templates/configset/configset.rb +2 -16
- data/lib/templates/examples/configset/configset.rb +16 -0
- data/lib/templates/helper/%underscore_name%_helper.rb.tt +1 -1
- data/lib/templates/hook/config/hooks.rb.tt +14 -0
- data/lono.gemspec +1 -1
- metadata +99 -93
- data/lib/lono/app_file/base.rb +0 -28
- data/lib/lono/app_file/build/lambda_layer.rb +0 -20
- data/lib/lono/app_file/build.rb +0 -79
- data/lib/lono/app_file/registry/item.rb +0 -24
- data/lib/lono/app_file/registry.rb +0 -16
- data/lib/lono/app_file/upload.rb +0 -12
- data/lib/lono/builder/context/loader/load_files.rb +0 -23
- data/lib/lono/builder/context/loader.rb +0 -35
- data/lib/lono/builder/context/params.rb +0 -7
- data/lib/lono/builder/template/configset_injector.rb +0 -52
- data/lib/lono/builder/template/dsl/evaluator/helpers/core_helper.rb +0 -14
- data/lib/lono/builder/template/dsl/evaluator/helpers/file_helper.rb +0 -44
- data/lib/lono/builder/template/dsl/evaluator/helpers/s3_helper.rb +0 -16
- data/lib/lono/builder/template/dsl/evaluator/helpers.rb +0 -16
- data/lib/lono/builder/template/dsl/evaluator/squeezer.rb +0 -24
- data/lib/lono/builder/template/dsl/evaluator/syntax/extend_with.rb +0 -9
- data/lib/lono/builder/template/dsl/evaluator/syntax.rb +0 -11
- data/lib/lono/builder/template/dsl/evaluator.rb +0 -45
- data/lib/lono/builder/template/dsl/finalizer.rb +0 -12
- data/lib/lono/builder/template/evaluate.rb +0 -52
- data/lib/lono/builder/template/post_processor.rb +0 -67
- data/lib/lono/cli/build.rb +0 -101
- data/lib/lono/cli/code.rb +0 -22
- data/lib/lono/cli/help/blueprint/new.md +0 -56
- data/lib/lono/cli/new/extension.rb +0 -57
- data/lib/lono/configset/builder.rb +0 -59
- data/lib/lono/configset/combiner.rb +0 -164
- data/lib/lono/configset/evaluate_file.rb +0 -8
- data/lib/lono/configset/meta/dsl.rb +0 -12
- data/lib/lono/configset/meta.rb +0 -19
- data/lib/lono/configset/s3_file/build.rb +0 -34
- data/lib/lono/configset/s3_file/item.rb +0 -38
- data/lib/lono/configset/s3_file/registry.rb +0 -12
- data/lib/lono/configset/s3_file/upload.rb +0 -12
- data/lib/lono/configset/strategy/base.rb +0 -83
- data/lib/lono/configset/strategy/helpers/dsl/core.rb +0 -18
- data/lib/lono/configset/strategy/helpers/dsl.rb +0 -8
- data/lib/lono/configset/strategy/helpers/erb.rb +0 -9
- data/lib/lono/extensions/dsl.rb +0 -8
- data/lib/lono/extensions/loader.rb +0 -19
- data/lib/lono/extensions.rb +0 -18
- data/lib/lono/importer/base.rb +0 -48
- data/lib/lono/importer/converter.rb +0 -19
- data/lib/lono/importer/download.rb +0 -46
- data/lib/lono/importer/dsl.rb +0 -36
- data/lib/lono/importer/params.rb +0 -56
- data/lib/lono/importer/service/coder.rb +0 -81
- data/lib/lono/inspector/base.rb +0 -32
- data/lib/lono/lookup.rb +0 -12
- data/lib/lono/seeder/service_role.rb +0 -11
- data/lib/lono/utils/context.rb +0 -15
- data/lib/lono/utils/item/file_methods.rb +0 -29
- data/lib/lono/utils/item/zip.rb +0 -42
- data/lib/templates/extension/lib/%extension_name%/autoloader.rb.tt +0 -23
- data/lib/templates/extension/lib/%extension_name%/helpers/mappings.rb.tt +0 -24
- data/lib/templates/extension/lib/%extension_name%/helpers/outputs.rb.tt +0 -7
- data/lib/templates/extension/lib/%extension_name%/helpers/parameters.rb.tt +0 -10
- data/lib/templates/extension/lib/%extension_name%/helpers/resources/resource.rb.tt +0 -4
- data/lib/templates/extension/lib/%extension_name%/helpers/variables.rb.tt +0 -6
- data/lib/templates/extension/lib/%extension_name%/version.rb.tt +0 -3
- data/lib/templates/extension/lib/%extension_name%.rb.tt +0 -8
@@ -0,0 +1,17 @@
|
|
1
|
+
module Lono
|
2
|
+
class Configset < Component
|
3
|
+
attr_reader :resource
|
4
|
+
attr_accessor :metadata
|
5
|
+
def initialize(options={})
|
6
|
+
super
|
7
|
+
@resource = options[:resource]
|
8
|
+
end
|
9
|
+
|
10
|
+
def path
|
11
|
+
return unless root
|
12
|
+
exts = %w[rb yml json] # rb highest precedence
|
13
|
+
paths = exts.map { |ext| "#{root}/configset.#{ext}" }
|
14
|
+
paths.find { |p| File.exist?(p) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/lono/core.rb
CHANGED
@@ -19,11 +19,21 @@ module Lono
|
|
19
19
|
end
|
20
20
|
memoize :app
|
21
21
|
|
22
|
+
def role
|
23
|
+
ENV['LONO_ROLE']
|
24
|
+
end
|
25
|
+
memoize :role
|
26
|
+
|
22
27
|
def env
|
23
28
|
ENV['LONO_ENV'] || 'dev'
|
24
29
|
end
|
25
30
|
memoize :env
|
26
31
|
|
32
|
+
def extra
|
33
|
+
ENV['LONO_EXTRA']
|
34
|
+
end
|
35
|
+
memoize :extra
|
36
|
+
|
27
37
|
def tmp_root
|
28
38
|
ENV['LONO_TMP_ROOT'] || "/tmp/lono"
|
29
39
|
end
|
@@ -37,7 +47,7 @@ module Lono
|
|
37
47
|
App.instance.configure(&block)
|
38
48
|
end
|
39
49
|
|
40
|
-
# Generally, use the
|
50
|
+
# Generally, use the Lono.config instead of App.instance.config since it guarantees the load_project_config call
|
41
51
|
def config
|
42
52
|
App.instance.load_project_config
|
43
53
|
App.instance.config
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Module
|
2
|
+
# Include all modules within the relative folder. IE: for dsl/syntax/mod/*
|
3
|
+
#
|
4
|
+
# include Common
|
5
|
+
# include Provider
|
6
|
+
# # etc
|
7
|
+
#
|
8
|
+
# Caller lines are different for OSes:
|
9
|
+
#
|
10
|
+
# windows: "C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/lono-1.1.1/lib/lono/builder.rb:34:in `build'"
|
11
|
+
# linux: "/home/ec2-user/.rvm/gems/ruby-3.0.3/gems/lono-1.1.1/lib/lono/compiler/dsl/syntax/mod.rb:4:in `<module:Mod>'"
|
12
|
+
#
|
13
|
+
def include_modules(dir)
|
14
|
+
caller_line = caller[0]
|
15
|
+
parts = caller_line.split(':')
|
16
|
+
calling_file = caller_line.match(/^[a-zA-Z]:/) ? parts[1] : parts[0]
|
17
|
+
parent_dir = File.dirname(calling_file)
|
18
|
+
|
19
|
+
full_dir = "#{parent_dir}/#{dir}"
|
20
|
+
paths = Dir.glob("#{full_dir}/**/*.rb")
|
21
|
+
if paths.empty?
|
22
|
+
raise "Empty include_modules full_dir: #{full_dir}"
|
23
|
+
end
|
24
|
+
paths.each do |path|
|
25
|
+
regexp = Regexp.new(".*/lib/")
|
26
|
+
mod = path.sub(regexp, '').sub('.rb','').camelize
|
27
|
+
c = mod.constantize
|
28
|
+
include c if c.class == Module
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Object
|
2
|
+
# Load custom helper methods from project
|
3
|
+
def load_helper_files(dir, type: :blueprint)
|
4
|
+
paths = Dir.glob("#{dir}/**/*.rb")
|
5
|
+
paths.sort_by! { |p| p.size } # so namespaces are loaded first
|
6
|
+
paths.each do |path|
|
7
|
+
next unless File.file?(path)
|
8
|
+
|
9
|
+
filename = if type == :project
|
10
|
+
path.sub(%r{.*/helpers/[a-zA-Z\-_]+/},'').sub('.rb','')
|
11
|
+
else # blueprint, configset
|
12
|
+
path.sub(%r{.*/helpers/},'').sub('.rb','')
|
13
|
+
end
|
14
|
+
module_name = filename.camelize
|
15
|
+
|
16
|
+
# Prepend a period so require works when LONO_ROOT is set to a relative path without a period.
|
17
|
+
# Example: LONO_ROOT=tmp/lono_project
|
18
|
+
first_char = path[0..0]
|
19
|
+
path = "./#{path}" unless %w[. /].include?(first_char)
|
20
|
+
|
21
|
+
# Examples:
|
22
|
+
# project:
|
23
|
+
# path: app/helpers/custom/custom_helper.rb
|
24
|
+
# module_name: CustomHelper
|
25
|
+
# blueprint:
|
26
|
+
# path: app/blueprints/demo/helpers/outputs.rb
|
27
|
+
# module_name: Outputs
|
28
|
+
require path
|
29
|
+
self.class.send :include, module_name.constantize
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/lono/ext.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
class Lono::Files
|
2
|
+
class Base < Lono::CLI::Base
|
3
|
+
delegate :full_path, :output_path, :zip_name, :zip_path, to: :files
|
4
|
+
attr_reader :files
|
5
|
+
def initialize(options={})
|
6
|
+
super
|
7
|
+
# @files is reference to Lono::Files self instance
|
8
|
+
# IE: Lono::Files instance is the caller
|
9
|
+
@files = options[:files]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'shellwords'
|
2
2
|
|
3
|
-
|
3
|
+
class Lono::Files::Builder::LambdaLayer
|
4
4
|
module Rsync
|
5
|
-
include Lono::Utils::Logging
|
6
|
-
|
7
5
|
def sh(command)
|
8
|
-
logger.
|
6
|
+
logger.debug "=> #{command}"
|
9
7
|
out = `#{command}`
|
10
|
-
logger.
|
8
|
+
logger.debug out
|
11
9
|
success = $?.success?
|
12
10
|
raise("ERROR: running command #{command}").color(:red) unless success
|
13
11
|
success
|
@@ -1,61 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class RubyPackager
|
4
|
-
include
|
5
|
-
|
6
|
-
def initialize(blueprint, registry_item)
|
7
|
-
@blueprint.name, @registry_item = blueprint, registry_item
|
8
|
-
|
9
|
-
@registry_name = @registry_item.name.sub(/\/$/,'')
|
10
|
-
@app_root = "#{@blueprint.root}/app/files/#{@registry_name}"
|
11
|
-
end
|
1
|
+
# Based on jets
|
2
|
+
class Lono::Files::Builder::LambdaLayer
|
3
|
+
class RubyPackager < Lono::Files::Base
|
4
|
+
include Rsync
|
12
5
|
|
13
6
|
def build
|
14
7
|
return unless gemfile_exist?
|
15
|
-
|
8
|
+
pretty_path = pretty_path("#{@blueprint.root}/#{@files.path}")
|
9
|
+
logger.debug "Packaging Lambda Layer #{pretty_path}"
|
10
|
+
check_ruby_version!
|
16
11
|
bundle_install
|
17
12
|
package
|
18
13
|
end
|
19
14
|
|
15
|
+
def check_ruby_version!
|
16
|
+
RubyVersion.new(@options).check!
|
17
|
+
end
|
18
|
+
|
20
19
|
# We consolidate all gems to opt
|
21
20
|
def package
|
22
|
-
setup_bundle_config(
|
23
|
-
# copy_cache_gems # TODO: might not need this cache
|
21
|
+
setup_bundle_config(compiled_area)
|
24
22
|
consolidate_gems_to_opt
|
25
23
|
end
|
26
24
|
|
27
|
-
# Also restructure the folder from:
|
28
|
-
# vendor/gems/ruby/2.5.0
|
29
|
-
# To:
|
30
|
-
# ruby/gems/2.5.0
|
31
|
-
#
|
32
|
-
# For Lambda Layer structure
|
33
|
-
def consolidate_gems_to_opt
|
34
|
-
src = "#{cache_area}/vendor/gems/ruby/#{ruby_folder}"
|
35
|
-
dest = "#{opt_area}/ruby/gems/#{ruby_folder}"
|
36
|
-
rsync_and_link(src, dest)
|
37
|
-
end
|
38
|
-
|
39
|
-
def rsync_and_link(src, dest)
|
40
|
-
FileUtils.mkdir_p(dest)
|
41
|
-
rsync(src, dest)
|
42
|
-
|
43
|
-
# create symlink in output path not the cache path
|
44
|
-
symlink_dest = "#{output_area}/vendor/gems/ruby/#{ruby_folder}"
|
45
|
-
logger.info "symlink_dest #{symlink_dest}"
|
46
|
-
FileUtils.rm_rf(symlink_dest) # blow away original 2.5.0 folder
|
47
|
-
|
48
|
-
# Create symlink that will point to the gems in the Lambda Layer:
|
49
|
-
# stage/opt/ruby/gems/2.5.0 -> /opt/ruby/gems/2.5.0
|
50
|
-
FileUtils.mkdir_p(File.dirname(symlink_dest))
|
51
|
-
FileUtils.ln_sf("/opt/ruby/gems/#{ruby_folder}", symlink_dest)
|
52
|
-
end
|
53
|
-
|
54
|
-
def ruby_folder
|
55
|
-
major, minor, _ = RUBY_VERSION.split('.')
|
56
|
-
[major, minor, '0'].join('.') # 2.5.1 => 2.5.0
|
57
|
-
end
|
58
|
-
|
59
25
|
# Installs gems on the current target system: both compiled and non-compiled.
|
60
26
|
# If user is on a macosx machine, macosx gems will be installed.
|
61
27
|
# If user is on a linux machine, linux gems will be installed.
|
@@ -68,9 +34,9 @@ class Lono::AppFile::Build::LambdaLayer
|
|
68
34
|
# project gets built again not all the gems from get installed from the
|
69
35
|
# beginning.
|
70
36
|
def bundle_install
|
71
|
-
logger.
|
37
|
+
logger.debug "Bundling #{cache_area}"
|
72
38
|
|
73
|
-
rsync(
|
39
|
+
rsync(compiled_area, cache_area)
|
74
40
|
|
75
41
|
# Uncomment out to always remove the cache/vendor/gems to debug
|
76
42
|
# FileUtils.rm_rf("#{cache_area}/vendor/gems")
|
@@ -85,15 +51,101 @@ class Lono::AppFile::Build::LambdaLayer
|
|
85
51
|
FileUtils.rm_rf("#{cache_area}/.bundle")
|
86
52
|
require "bundler" # dynamically require bundler so user can use any bundler
|
87
53
|
setup_bundle_config(cache_area)
|
88
|
-
|
54
|
+
Bundler.with_unbundled_env do
|
89
55
|
sh "cd #{cache_area} && env bundle install"
|
90
56
|
end
|
91
57
|
|
92
58
|
remove_bundled_with("#{cache_area}/Gemfile.lock")
|
93
59
|
# Fixes really tricky bug where Gemfile and Gemfile.lock is out-of-sync. Details: https://gist.github.com/tongueroo/b5b0d0c924a4a1633eee514795e4b04b
|
94
|
-
FileUtils.cp("#{cache_area}/Gemfile.lock",
|
60
|
+
FileUtils.cp("#{cache_area}/Gemfile.lock", compiled_area)
|
61
|
+
|
62
|
+
logger.debug 'Bundle install success.'
|
63
|
+
end
|
64
|
+
|
65
|
+
def setup_bundle_config(dir)
|
66
|
+
text =<<~EOL
|
67
|
+
---
|
68
|
+
BUNDLE_PATH: "vendor/gems"
|
69
|
+
BUNDLE_WITHOUT: "development:test"
|
70
|
+
EOL
|
71
|
+
bundle_config = "#{dir}/.bundle/config"
|
72
|
+
FileUtils.mkdir_p(File.dirname(bundle_config))
|
73
|
+
IO.write(bundle_config, text)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Examples:
|
77
|
+
#
|
78
|
+
# output/BLUEPRINT/lambda_layers/PATH/opt
|
79
|
+
# output/demo/lambda_layers/files/lambda-function/opt
|
80
|
+
# output/demo/lambda_layers/files/lambda-function # drop /opt to get dirname
|
81
|
+
#
|
82
|
+
# The build_parent is the parent folder because it can include cache and opt. Example tree:
|
83
|
+
#
|
84
|
+
# output
|
85
|
+
# └── demo
|
86
|
+
# └── lambda_layers
|
87
|
+
# └── files
|
88
|
+
# └── lambda-function # <= build_area
|
89
|
+
# ├── cache
|
90
|
+
# └── opt
|
91
|
+
#
|
92
|
+
def build_area
|
93
|
+
File.dirname(@files.output_path)
|
94
|
+
end
|
95
|
+
|
96
|
+
def cache_area
|
97
|
+
"#{build_area}/cache"
|
98
|
+
end
|
99
|
+
|
100
|
+
# Final artifact that will be zipped up
|
101
|
+
def opt_area
|
102
|
+
"#{build_area}/opt"
|
103
|
+
end
|
95
104
|
|
96
|
-
|
105
|
+
# Original source is compiled to output folder
|
106
|
+
#
|
107
|
+
# app/blueprints/demo/files/lambda-function/ - original
|
108
|
+
# output/demo/files/lambda-function/ - compiled
|
109
|
+
#
|
110
|
+
# Compiling is done beforehand to support .tt ERB in the files.
|
111
|
+
#
|
112
|
+
# Then it's moved again to a cache area to run `bundle`
|
113
|
+
# Then it's moved yet agaoin to an opt area to produce the final Lambda Layer artifact.
|
114
|
+
#
|
115
|
+
def compiled_area
|
116
|
+
@files.compiled_path
|
117
|
+
end
|
118
|
+
|
119
|
+
# Also restructure the folder from:
|
120
|
+
# vendor/gems/ruby/3.0.0
|
121
|
+
# To:
|
122
|
+
# ruby/gems/3.0.0
|
123
|
+
#
|
124
|
+
# For Lambda Layer structure
|
125
|
+
def consolidate_gems_to_opt
|
126
|
+
src = "#{cache_area}/vendor/gems/ruby/#{ruby_folder}"
|
127
|
+
dest = "#{opt_area}/ruby/gems/#{ruby_folder}"
|
128
|
+
rsync_and_link(src, dest)
|
129
|
+
end
|
130
|
+
|
131
|
+
def rsync_and_link(src, dest)
|
132
|
+
FileUtils.mkdir_p(dest)
|
133
|
+
rsync(src, dest)
|
134
|
+
|
135
|
+
# create symlink in output path not the cache path
|
136
|
+
symlink_dest = "#{compiled_area}/vendor/gems/ruby/#{ruby_folder}"
|
137
|
+
logger.debug "symlink_dest #{symlink_dest}"
|
138
|
+
FileUtils.rm_rf(symlink_dest) # blow away original 3.0.0 folder
|
139
|
+
|
140
|
+
# Create symlink that will point to the gems in the Lambda Layer:
|
141
|
+
# stage/opt/ruby/gems/3.0.0 -> /opt/ruby/gems/3.0.0
|
142
|
+
FileUtils.mkdir_p(File.dirname(symlink_dest))
|
143
|
+
FileUtils.ln_sf("/opt/ruby/gems/#{ruby_folder}", symlink_dest)
|
144
|
+
end
|
145
|
+
|
146
|
+
def ruby_folder
|
147
|
+
major, minor, _ = RUBY_VERSION.split('.')
|
148
|
+
[major, minor, '0'].join('.') # 3.0.1 => 3.0.0
|
97
149
|
end
|
98
150
|
|
99
151
|
# Remove the BUNDLED WITH line since we don't control the bundler gem version on AWS Lambda
|
@@ -118,35 +170,8 @@ class Lono::AppFile::Build::LambdaLayer
|
|
118
170
|
IO.write(gemfile_lock, content)
|
119
171
|
end
|
120
172
|
|
121
|
-
def setup_bundle_config(dir)
|
122
|
-
text =<<-EOL
|
123
|
-
---
|
124
|
-
BUNDLE_PATH: "vendor/gems"
|
125
|
-
BUNDLE_WITHOUT: "development:test"
|
126
|
-
EOL
|
127
|
-
bundle_config = "#{dir}/.bundle/config"
|
128
|
-
FileUtils.mkdir_p(File.dirname(bundle_config))
|
129
|
-
IO.write(bundle_config, text)
|
130
|
-
end
|
131
|
-
|
132
|
-
def output_area
|
133
|
-
"#{Lono.root}/output/#{@blueprint.name}/files/#{@registry_name}"
|
134
|
-
end
|
135
|
-
|
136
|
-
def build_area
|
137
|
-
"#{Lono.root}/output/#{@blueprint.name}/lambda_layers/#{@registry_name}"
|
138
|
-
end
|
139
|
-
|
140
|
-
def cache_area
|
141
|
-
"#{build_area}/cache"
|
142
|
-
end
|
143
|
-
|
144
|
-
def opt_area
|
145
|
-
"#{build_area}/opt"
|
146
|
-
end
|
147
|
-
|
148
173
|
def gemfile_exist?
|
149
|
-
gemfile_path = "#{@
|
174
|
+
gemfile_path = "#{@files.full_path}/Gemfile"
|
150
175
|
File.exist?(gemfile_path)
|
151
176
|
end
|
152
177
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Lono::Files::Builder::LambdaLayer
|
2
|
+
class RubyVersion < Lono::Files::Base
|
3
|
+
def initialize(options={})
|
4
|
+
# cfn passed from Finalizer::Files::Build#build_files to
|
5
|
+
# Lono::Files#build_lambda_layer(@cfn)
|
6
|
+
# This because Lono::Files at initialization only has registration info
|
7
|
+
# The build info is passed to the build_lambda_layer method
|
8
|
+
@cfn = options[:cfn]
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def check!
|
13
|
+
# IE: logical_id = LayerVersion
|
14
|
+
# attrs = attrs with attrs['Properties']
|
15
|
+
logical_id, attrs = @cfn['Resources'].find do |logical_id, attrs|
|
16
|
+
attrs.dig('Properties', 'Content', 'S3Key') == @files.marker
|
17
|
+
end
|
18
|
+
props = attrs['Properties']
|
19
|
+
major, minor, _ = RUBY_VERSION.split('.')
|
20
|
+
current_ruby = "ruby#{major}.#{minor}"
|
21
|
+
ok = props['CompatibleRuntimes'].include?(current_ruby)
|
22
|
+
return if ok
|
23
|
+
|
24
|
+
runtimes = props['CompatibleRuntimes'].map { |s| s.sub('ruby','') }.join(', ')
|
25
|
+
logger.error "ERROR: Current Ruby Version does not match the Lambda Layer Ruby Version".color(:red)
|
26
|
+
logger.error <<~EOL
|
27
|
+
Current Ruby: #{RUBY_VERSION}
|
28
|
+
Lambda Layer Ruby Version: #{runtimes}
|
29
|
+
|
30
|
+
Lono is unable to package up a Lambda Layer
|
31
|
+
unless you use the same Ruby version on this machine.
|
32
|
+
EOL
|
33
|
+
logger.error "Resource: #{logical_id}"
|
34
|
+
logger.error YAML.dump(attrs)
|
35
|
+
exit 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Lono::Files::Builder
|
2
|
+
class LambdaLayer < Lono::Files::Base
|
3
|
+
def run
|
4
|
+
layer = @options[:layer]
|
5
|
+
return unless layer # triggers Lambda Layer building
|
6
|
+
unless layer =~ /ruby/
|
7
|
+
logger.warn "WARN: Currently only support Ruby lambda layers automatically".color(:yellow)
|
8
|
+
return
|
9
|
+
end
|
10
|
+
|
11
|
+
klass_name = "Lono::Files::Builder::LambdaLayer::#{layer.camelize}Packager"
|
12
|
+
klass = klass_name.constantize
|
13
|
+
packager = klass.new(@options)
|
14
|
+
packager.build
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Lono::Files
|
2
|
+
class Builder < Base
|
3
|
+
extend Memoist
|
4
|
+
include Lono::Builder::Context
|
5
|
+
include Lono::Builder::Dsl::Syntax
|
6
|
+
# Tricky must define files again to avoid conflict with files from loading the Dsl::Syntax
|
7
|
+
attr_reader :files
|
8
|
+
|
9
|
+
def run
|
10
|
+
load_context
|
11
|
+
if File.directory?(full_path)
|
12
|
+
directory(@files)
|
13
|
+
else
|
14
|
+
template(@files)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def template(files)
|
19
|
+
sequence.send(:set_template_paths, @blueprint.root)
|
20
|
+
src = files.path
|
21
|
+
dest = files.output_path
|
22
|
+
sequence.template(src, dest)
|
23
|
+
end
|
24
|
+
|
25
|
+
def directory(files)
|
26
|
+
src = files.full_path
|
27
|
+
sequence.send(:set_template_paths, src)
|
28
|
+
sequence.destination_root = @files.output_path
|
29
|
+
sequence.directory(".", verbose: false, force: true, context: binding) # Thor::Action
|
30
|
+
end
|
31
|
+
|
32
|
+
def sequence
|
33
|
+
Lono::CLI::New::Sequence.new(@options)
|
34
|
+
end
|
35
|
+
memoize :sequence
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
class Lono::Files
|
4
|
+
class Compressor < Base
|
5
|
+
def run
|
6
|
+
if File.directory?(output_path)
|
7
|
+
zip_directory
|
8
|
+
else
|
9
|
+
zip_file
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def zip_file
|
14
|
+
logger.debug "Zipping file to #{pretty_path(zip_path)}"
|
15
|
+
# create zipfile at same level of file
|
16
|
+
command = "cd #{File.dirname(output_path)} && zip -q #{zip_name} #{File.basename(output_path)}"
|
17
|
+
execute_zip(command)
|
18
|
+
end
|
19
|
+
|
20
|
+
def zip_directory
|
21
|
+
logger.debug "Zipping folder to #{zip_path}"
|
22
|
+
command = "cd #{output_path} && zip --symlinks -rq #{zip_name} ." # create zipfile witih directory
|
23
|
+
execute_zip(command)
|
24
|
+
FileUtils.mv("#{output_path}/#{zip_name}", "#{File.dirname(output_path)}/#{zip_name}") # move zip back to the parent directory
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def execute_zip(command)
|
29
|
+
check_zip_installed!
|
30
|
+
logger.debug "=> #{command}".color(:green)
|
31
|
+
`#{command}`
|
32
|
+
return if $?.success?
|
33
|
+
logger.info "ERROR: Fail trying to zip files".color(:red)
|
34
|
+
logger.info "Command: #{command}".color(:red)
|
35
|
+
exit 1
|
36
|
+
end
|
37
|
+
|
38
|
+
@@zip_installed = false
|
39
|
+
def check_zip_installed!
|
40
|
+
@@zip_installed = system("type zip > /dev/null 2>&1")
|
41
|
+
if @@zip_installed
|
42
|
+
@@zip_installed = true
|
43
|
+
return
|
44
|
+
end
|
45
|
+
logger.error "ERROR: The command 'zip' is not installed.".color(:red)
|
46
|
+
logger.error <<~EOL
|
47
|
+
The file helper requires the zip command.
|
48
|
+
Please install the zip command on this system.
|
49
|
+
EOL
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Lono::Files::Concerns
|
2
|
+
module PostProcessing
|
3
|
+
extend Memoist
|
4
|
+
|
5
|
+
def build
|
6
|
+
Lono::Files::Builder.new(@options.merge(files: self)).run
|
7
|
+
end
|
8
|
+
|
9
|
+
def build_lambda_layer(cfn)
|
10
|
+
Lono::Files::Builder::LambdaLayer.new(@options.merge(files: self, cfn: cfn)).run
|
11
|
+
end
|
12
|
+
|
13
|
+
def compress
|
14
|
+
Lono::Files::Compressor.new(@options.merge(files: self)).run
|
15
|
+
end
|
16
|
+
|
17
|
+
def upload
|
18
|
+
uploader.upload # Lono::S3::Uploader#upload
|
19
|
+
end
|
20
|
+
|
21
|
+
delegate :s3_path, :s3_key, to: :uploader
|
22
|
+
def uploader
|
23
|
+
Lono::S3::Uploader.new(zip_path)
|
24
|
+
end
|
25
|
+
memoize :uploader
|
26
|
+
|
27
|
+
def zip_name
|
28
|
+
name = File.basename(full_path)
|
29
|
+
name << "-layer" if layer
|
30
|
+
"#{name}-#{Lono::Md5.sum(full_path)}.zip"
|
31
|
+
end
|
32
|
+
|
33
|
+
def zip_path
|
34
|
+
"#{File.dirname(output_path)}/#{zip_name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def output_path
|
38
|
+
if layer
|
39
|
+
# For Lambda Layer the final output path is the opt folder, where final artifact is zipped
|
40
|
+
"#{Lono.root}/output/#{@blueprint.name}/layer/#{path}/opt" # Note: layer and opt
|
41
|
+
else
|
42
|
+
# For normal files the final output path in the compiled path
|
43
|
+
compiled_path
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Also used by LambdaLayer::RubyPackager#compiled_area
|
48
|
+
def compiled_path
|
49
|
+
"#{Lono.root}/output/#{@blueprint.name}/normal/#{path}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Lono::Files::Concerns
|
2
|
+
module Registration
|
3
|
+
def call_line
|
4
|
+
@caller.find do |line|
|
5
|
+
line.include?(Lono.root.to_s)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# IE:
|
10
|
+
# LONO:://files/function-normal
|
11
|
+
# LONO:://files/function-layer
|
12
|
+
def marker
|
13
|
+
"LONO://#{@path}-#{@type}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/lono/files.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# Class name is Lono::Files because can represent a single file or a directory.
|
2
|
+
# Also, it avoids conflicting with the stdlib File class name.
|
3
|
+
# Files is like a "FileList". Using shorter Files name.
|
4
|
+
module Lono
|
5
|
+
class Files < Lono::CLI::Base
|
6
|
+
include Concerns::Registration
|
7
|
+
include Concerns::PostProcessing
|
8
|
+
|
9
|
+
attr_reader :path, :layer, :type
|
10
|
+
def initialize(options={})
|
11
|
+
super
|
12
|
+
@path = options[:path]
|
13
|
+
@layer = options[:layer]
|
14
|
+
@type = @layer ? "layer" : "normal"
|
15
|
+
@caller = options[:caller] # original caller stack at registration time
|
16
|
+
end
|
17
|
+
|
18
|
+
def full_path
|
19
|
+
"#{@blueprint.root}/#{@path}"
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def register(options={})
|
24
|
+
path = options[:path]
|
25
|
+
layer = options[:layer]
|
26
|
+
# Registration uniquess based on both path and layer option
|
27
|
+
file = files.find { |f| f.path == path && f.layer == layer }
|
28
|
+
unless file
|
29
|
+
file = Files.new(options.merge(caller: caller))
|
30
|
+
files << file
|
31
|
+
end
|
32
|
+
file.marker
|
33
|
+
end
|
34
|
+
|
35
|
+
delegate :empty?, :files, to: :files
|
36
|
+
def files
|
37
|
+
Registry.files
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|