lono 8.0.0.pre.rc3 → 8.0.0.pre.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +84 -0
  3. data/.github/ISSUE_TEMPLATE/documentation.md +12 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +64 -0
  5. data/.github/ISSUE_TEMPLATE/question.md +14 -0
  6. data/.github/ISSUE_TEMPLATE.md +7 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +50 -0
  8. data/CHANGELOG.md +33 -0
  9. data/lib/lono/app.rb +37 -3
  10. data/lib/lono/builder/allow.rb +1 -1
  11. data/lib/lono/builder/configset/definition/context.rb +50 -9
  12. data/lib/lono/builder/configset/definition/dsl/syntax/content.rb +3 -7
  13. data/lib/lono/builder/context.rb +1 -1
  14. data/lib/lono/builder/dsl/finalizer/files/build.rb +4 -12
  15. data/lib/lono/builder/dsl/finalizer/files/replace.rb +6 -1
  16. data/lib/lono/builder/dsl/helpers/files.rb +2 -2
  17. data/lib/lono/builder/dsl/helpers/s3.rb +5 -7
  18. data/lib/lono/builder/dsl/helpers/stack.rb +2 -4
  19. data/lib/lono/builder/dsl/helpers/template_file.rb +2 -2
  20. data/lib/lono/builder/dsl/syntax/core/squeezer.rb +3 -1
  21. data/lib/lono/builder/dsl/syntax/fn.rb +0 -2
  22. data/lib/lono/builder/dsl.rb +1 -1
  23. data/lib/lono/builder/param.rb +1 -1
  24. data/lib/lono/builder/template.rb +1 -3
  25. data/lib/lono/builder.rb +39 -0
  26. data/lib/lono/bundler/util/git.rb +18 -16
  27. data/lib/lono/cfn/base.rb +2 -2
  28. data/lib/lono/cfn/concerns/build.rb +1 -1
  29. data/lib/lono/cfn/delete.rb +5 -2
  30. data/lib/lono/cfn/deploy/rollback.rb +1 -3
  31. data/lib/lono/cfn/deploy.rb +16 -4
  32. data/lib/lono/cfn/plan/changeset.rb +1 -1
  33. data/lib/lono/cli/base.rb +1 -0
  34. data/lib/lono/cli/help/new/helper.md +27 -0
  35. data/lib/lono/cli/help/new/hook.md +14 -0
  36. data/lib/lono/cli/help/new/project.md +3 -10
  37. data/lib/lono/cli/iam.rb +27 -0
  38. data/lib/lono/cli/new/blueprint.rb +2 -4
  39. data/lib/lono/cli/new/helper.rb +35 -8
  40. data/lib/lono/cli/new/hook.rb +32 -0
  41. data/lib/lono/cli/new.rb +8 -4
  42. data/lib/lono/cli/script/build.rb +0 -5
  43. data/lib/lono/{inspector → cli}/summary.rb +23 -30
  44. data/lib/lono/cli.rb +9 -7
  45. data/lib/lono/command.rb +28 -1
  46. data/lib/lono/core.rb +10 -0
  47. data/lib/lono/{utils → files/builder/lambda_layer}/rsync.rb +3 -5
  48. data/lib/lono/files/builder/lambda_layer/ruby_packager.rb +178 -0
  49. data/lib/lono/files/builder/lambda_layer/ruby_version.rb +38 -0
  50. data/lib/lono/files/builder/lambda_layer.rb +17 -0
  51. data/lib/lono/files/concerns/post_processing.rb +19 -2
  52. data/lib/lono/files/concerns/registration.rb +4 -1
  53. data/lib/lono/files.rb +6 -2
  54. data/lib/lono/hooks/builder.rb +50 -0
  55. data/lib/lono/hooks/concern.rb +9 -0
  56. data/lib/lono/hooks/dsl.rb +20 -0
  57. data/lib/lono/hooks/runner.rb +46 -0
  58. data/lib/lono/layering/layer.rb +63 -41
  59. data/lib/lono/names.rb +6 -9
  60. data/lib/lono/s3/bucket.rb +17 -11
  61. data/lib/lono/s3/uploader.rb +4 -0
  62. data/lib/lono/script/build.rb +0 -5
  63. data/lib/lono/seeder.rb +1 -1
  64. data/lib/lono/utils/sh.rb +32 -0
  65. data/lib/lono/utils.rb +5 -0
  66. data/lib/lono/version.rb +1 -1
  67. data/lib/templates/hook/config/hooks.rb.tt +14 -0
  68. data/lono.gemspec +1 -1
  69. metadata +27 -30
  70. data/lib/lono/builder/template/post_processor.rb +0 -67
  71. data/lib/lono/cli/build.rb +0 -47
  72. data/lib/lono/cli/code.rb +0 -22
  73. data/lib/lono/cli/help/blueprint/new.md +0 -56
  74. data/lib/lono/cli/help/new/helper/blueprint.md +0 -17
  75. data/lib/lono/cli/help/new/helper/project.md +0 -16
  76. data/lib/lono/cli/new/extension.rb +0 -57
  77. data/lib/lono/cli/new/helper/blueprint.rb +0 -26
  78. data/lib/lono/cli/new/helper/project.rb +0 -24
  79. data/lib/lono/importer/base.rb +0 -48
  80. data/lib/lono/importer/converter.rb +0 -19
  81. data/lib/lono/importer/download.rb +0 -46
  82. data/lib/lono/importer/dsl.rb +0 -36
  83. data/lib/lono/importer/params.rb +0 -56
  84. data/lib/lono/importer/service/coder.rb +0 -85
  85. data/lib/lono/inspector/base.rb +0 -32
  86. data/lib/templates/extension/lib/%extension_name%/autoloader.rb.tt +0 -23
  87. data/lib/templates/extension/lib/%extension_name%/helpers/mappings.rb.tt +0 -24
  88. data/lib/templates/extension/lib/%extension_name%/helpers/outputs.rb.tt +0 -7
  89. data/lib/templates/extension/lib/%extension_name%/helpers/parameters.rb.tt +0 -10
  90. data/lib/templates/extension/lib/%extension_name%/helpers/resources/resource.rb.tt +0 -4
  91. data/lib/templates/extension/lib/%extension_name%/helpers/variables.rb.tt +0 -6
  92. data/lib/templates/extension/lib/%extension_name%/version.rb.tt +0 -3
  93. data/lib/templates/extension/lib/%extension_name%.rb.tt +0 -8
@@ -0,0 +1,178 @@
1
+ # Based on jets
2
+ class Lono::Files::Builder::LambdaLayer
3
+ class RubyPackager < Lono::Files::Base
4
+ include Rsync
5
+
6
+ def build
7
+ return unless gemfile_exist?
8
+ pretty_path = pretty_path("#{@blueprint.root}/#{@files.path}")
9
+ logger.debug "Packaging Lambda Layer #{pretty_path}"
10
+ check_ruby_version!
11
+ bundle_install
12
+ package
13
+ end
14
+
15
+ def check_ruby_version!
16
+ RubyVersion.new(@options).check!
17
+ end
18
+
19
+ # We consolidate all gems to opt
20
+ def package
21
+ setup_bundle_config(compiled_area)
22
+ consolidate_gems_to_opt
23
+ end
24
+
25
+ # Installs gems on the current target system: both compiled and non-compiled.
26
+ # If user is on a macosx machine, macosx gems will be installed.
27
+ # If user is on a linux machine, linux gems will be installed.
28
+ #
29
+ # Copies Gemfile* to /tmp/jets/demo/cache folder and installs
30
+ # gems with bundle install from there.
31
+ #
32
+ # We take the time to copy Gemfile and bundle into a separate directory
33
+ # because it gets left around to act as a 'cache'. So, when the builds the
34
+ # project gets built again not all the gems from get installed from the
35
+ # beginning.
36
+ def bundle_install
37
+ logger.debug "Bundling #{cache_area}"
38
+
39
+ rsync(compiled_area, cache_area)
40
+
41
+ # Uncomment out to always remove the cache/vendor/gems to debug
42
+ # FileUtils.rm_rf("#{cache_area}/vendor/gems")
43
+
44
+ # Remove .bundle folder so .bundle/config doesnt affect how gems are packages
45
+ # Not using BUNDLE_IGNORE_CONFIG=1 to allow home ~/.bundle/config to affect bundling though.
46
+ # This is useful if you have private gems sources that require authentication. Example:
47
+ #
48
+ # bundle config gems.myprivatesource.com user:pass
49
+ #
50
+
51
+ FileUtils.rm_rf("#{cache_area}/.bundle")
52
+ require "bundler" # dynamically require bundler so user can use any bundler
53
+ setup_bundle_config(cache_area)
54
+ Bundler.with_unbundled_env do
55
+ sh "cd #{cache_area} && env bundle install"
56
+ end
57
+
58
+ remove_bundled_with("#{cache_area}/Gemfile.lock")
59
+ # Fixes really tricky bug where Gemfile and Gemfile.lock is out-of-sync. Details: https://gist.github.com/tongueroo/b5b0d0c924a4a1633eee514795e4b04b
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
104
+
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
149
+ end
150
+
151
+ # Remove the BUNDLED WITH line since we don't control the bundler gem version on AWS Lambda
152
+ # And this can cause issues with require 'bundler/setup'
153
+ def remove_bundled_with(gemfile_lock)
154
+ lines = IO.readlines(gemfile_lock)
155
+
156
+ # amount is the number of lines to remove
157
+ new_lines, capture, count, amount = [], true, 0, 2
158
+ lines.each do |l|
159
+ capture = false if l.include?('BUNDLED WITH')
160
+ if capture
161
+ new_lines << l
162
+ end
163
+ if capture == false
164
+ count += 1
165
+ capture = count > amount # renable capture
166
+ end
167
+ end
168
+
169
+ content = new_lines.join('')
170
+ IO.write(gemfile_lock, content)
171
+ end
172
+
173
+ def gemfile_exist?
174
+ gemfile_path = "#{@files.full_path}/Gemfile"
175
+ File.exist?(gemfile_path)
176
+ end
177
+ end
178
+ 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
@@ -6,6 +6,10 @@ module Lono::Files::Concerns
6
6
  Lono::Files::Builder.new(@options.merge(files: self)).run
7
7
  end
8
8
 
9
+ def build_lambda_layer(cfn)
10
+ Lono::Files::Builder::LambdaLayer.new(@options.merge(files: self, cfn: cfn)).run
11
+ end
12
+
9
13
  def compress
10
14
  Lono::Files::Compressor.new(@options.merge(files: self)).run
11
15
  end
@@ -21,7 +25,9 @@ module Lono::Files::Concerns
21
25
  memoize :uploader
22
26
 
23
27
  def zip_name
24
- "#{File.basename(full_path)}-#{Lono::Md5.sum(full_path)}.zip"
28
+ name = File.basename(full_path)
29
+ name << "-layer" if layer
30
+ "#{name}-#{Lono::Md5.sum(full_path)}.zip"
25
31
  end
26
32
 
27
33
  def zip_path
@@ -29,7 +35,18 @@ module Lono::Files::Concerns
29
35
  end
30
36
 
31
37
  def output_path
32
- "#{Lono.root}/output/#{@blueprint.name}/#{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}"
33
50
  end
34
51
  end
35
52
  end
@@ -6,8 +6,11 @@ module Lono::Files::Concerns
6
6
  end
7
7
  end
8
8
 
9
+ # IE:
10
+ # LONO:://files/function-normal
11
+ # LONO:://files/function-layer
9
12
  def marker
10
- "LONO://#{@path}"
13
+ "LONO://#{@path}-#{@type}"
11
14
  end
12
15
  end
13
16
  end
data/lib/lono/files.rb CHANGED
@@ -6,10 +6,12 @@ module Lono
6
6
  include Concerns::Registration
7
7
  include Concerns::PostProcessing
8
8
 
9
- attr_reader :path
9
+ attr_reader :path, :layer, :type
10
10
  def initialize(options={})
11
11
  super
12
12
  @path = options[:path]
13
+ @layer = options[:layer]
14
+ @type = @layer ? "layer" : "normal"
13
15
  @caller = options[:caller] # original caller stack at registration time
14
16
  end
15
17
 
@@ -20,7 +22,9 @@ module Lono
20
22
  class << self
21
23
  def register(options={})
22
24
  path = options[:path]
23
- file = files.find { |f| f.path == 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 }
24
28
  unless file
25
29
  file = Files.new(options.merge(caller: caller))
26
30
  files << file
@@ -0,0 +1,50 @@
1
+ module Lono::Hooks
2
+ class Builder
3
+ extend Memoist
4
+ include Dsl
5
+ include DslEvaluator
6
+ include Lono::Utils
7
+
8
+ # IE: dsl_file: config/hooks.rb
9
+ attr_accessor :name
10
+ def initialize(blueprint, name)
11
+ @blueprint, @name = blueprint, name
12
+ @hooks = {before: {}, after: {}}
13
+ end
14
+
15
+ def build
16
+ evaluate_file("#{Lono.root}/config/hooks.rb")
17
+ evaluate_file("#{@blueprint.root}/config/hooks.rb")
18
+ @hooks.deep_stringify_keys!
19
+ end
20
+ memoize :build
21
+
22
+ def run_hooks
23
+ build
24
+ run_each_hook("before")
25
+ out = yield if block_given?
26
+ run_each_hook("after")
27
+ out
28
+ end
29
+
30
+ def run_each_hook(type)
31
+ hooks = @hooks.dig(type, @name) || []
32
+ hooks.each do |hook|
33
+ run_hook(type, hook)
34
+ end
35
+ end
36
+
37
+ def run_hook(type, hook)
38
+ return unless run?(hook)
39
+
40
+ id = "#{type} #{@name}"
41
+ label = " label: #{hook["label"]}" if hook["label"]
42
+ logger.info "Hook: Running #{id} hook#{label}".color(:cyan) if Lono.config.hooks.show
43
+ Runner.new(@blueprint, hook).run
44
+ end
45
+
46
+ def run?(hook)
47
+ !!hook["execute"]
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,9 @@
1
+ module Lono::Hooks
2
+ module Concern
3
+ def run_hooks(name, &block)
4
+ hooks = Builder.new(@blueprint, name)
5
+ hooks.build # build hooks
6
+ hooks.run_hooks(&block)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,20 @@
1
+ module Lono::Hooks
2
+ module Dsl
3
+ def before(*commands, **props)
4
+ commands.each do |name|
5
+ each_hook(:before, name, props)
6
+ end
7
+ end
8
+
9
+ def after(*commands, **props)
10
+ commands.each do |name|
11
+ each_hook(:after, name, props)
12
+ end
13
+ end
14
+
15
+ def each_hook(type, name, props={})
16
+ @hooks[type][name] ||= []
17
+ @hooks[type][name] << props
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,46 @@
1
+ module Lono::Hooks
2
+ class Runner
3
+ include Lono::Utils
4
+
5
+ # exposing blueprint and hook so lono hooks have access to them via runner context. IE:
6
+ #
7
+ # class EnvExporter
8
+ # def call(runner)
9
+ # puts "runner.hook #{runner.hook}"
10
+ # end
11
+ # end
12
+ #
13
+ # Docs: http://lono.cloud/docs/config/hooks/ruby/#method-argument
14
+ #
15
+ attr_reader :blueprint, :hook
16
+ def initialize(blueprint, hook)
17
+ @blueprint, @hook = blueprint, hook
18
+ @execute = @hook["execute"]
19
+ end
20
+
21
+ def run
22
+ case @execute
23
+ when String
24
+ sh(@execute, exit_on_fail: @hook["exit_on_fail"])
25
+ when -> (e) { e.respond_to?(:public_instance_methods) && e.public_instance_methods.include?(:call) }
26
+ executor = @execute.new
27
+ when -> (e) { e.respond_to?(:call) }
28
+ executor = @execute
29
+ else
30
+ logger.warn "WARN: execute option not set for hook: #{@hook.inspect}"
31
+ end
32
+
33
+ return unless executor
34
+
35
+ meth = executor.method(:call)
36
+ case meth.arity
37
+ when 0
38
+ executor.call # backwards compatibility
39
+ when 1
40
+ executor.call(self)
41
+ else
42
+ raise "The #{executor} call method definition has been more than 1 arguments and is not supported"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -31,30 +31,18 @@ module Lono::Layering
31
31
  paths
32
32
  end
33
33
 
34
- def full_layering
35
- # layers defined in Lono::Layering module
36
- all = layers.map { |layer| layer.sub(/\/$/,'') } # strip trailing slash
37
- all.inject([]) do |sum, layer|
38
- sum += layer_levels(layer) unless layer.nil?
39
- sum
34
+ def full_layers(dir)
35
+ layers = layer_levels("#{dir}/#{@type}") # root
36
+ if Lono.role
37
+ layers += layer_levels("#{dir}/#{@type}/#{Lono.role}")
40
38
  end
41
- end
42
-
43
- # interface method
44
- def main_layers
45
- [
46
- '',
47
- region,
48
- account,
49
- "#{account}/#{region}",
50
- ]
51
- end
52
-
53
- def account
54
- name = aws_data.account
55
- # friendly name mapping
56
- names = Lono.config.layering.names.stringify_keys
57
- names[name] || name
39
+ if Lono.app
40
+ layers += layer_levels("#{dir}/#{@type}/#{Lono.app}")
41
+ end
42
+ if Lono.app && Lono.role
43
+ layers += layer_levels("#{dir}/#{@type}/#{Lono.app}/#{Lono.role}")
44
+ end
45
+ layers
58
46
  end
59
47
 
60
48
  # adds prefix and to each layer pair that has base and Lono.env. IE:
@@ -62,19 +50,53 @@ module Lono::Layering
62
50
  # "#{prefix}/base"
63
51
  # "#{prefix}/#{Lono.env}"
64
52
  #
53
+ # Params Layers:
54
+ # config/blueprints/demo/params/txt
55
+ # config/blueprints/demo/params/base.txt
56
+ # config/blueprints/demo/params/dev.txt
65
57
  def layer_levels(prefix=nil)
66
- levels = ["base", Lono.env]
58
+ levels = ["", "base", Lono.env]
59
+ levels << "#{Lono.env}-#{Lono.extra}" if Lono.extra
67
60
  levels.map! do |i|
68
- # base layer has prefix of '', reject with blank so it doesnt produce '//'
69
61
  [prefix, i].reject(&:blank?).join('/')
70
62
  end
71
- levels.unshift(prefix) # unless prefix.blank? # IE: params/us-west-2.txt
63
+ levels.map! { |level| level.sub(/\/$/,'') } # strip trailing slash
64
+
65
+ # layers = pre_layers + main_layers + post_layers
66
+ levels = layers.inject([]) do |sum, layer|
67
+ layer_levels = levels.map do |level|
68
+ [level, layer].reject(&:blank?).join('/')
69
+ end
70
+ sum += layer_levels
71
+ sum
72
+ end
73
+
72
74
  levels
73
75
  end
74
76
 
77
+ # Interface method: layers = pre_layers + main_layers + post_layers
78
+ # Simple layering is default. Can set with:
79
+ #
80
+ # config.layering.mode = "simple" # simple of full
81
+ #
82
+ def main_layers
83
+ if Lono.config.layering.mode == "simple"
84
+ ['']
85
+ else # full
86
+ # includes region, account, and account/region layers
87
+ # More powerful but less used and more complex to understand
88
+ [
89
+ '',
90
+ region,
91
+ account,
92
+ "#{account}/#{region}",
93
+ ]
94
+ end
95
+ end
96
+
75
97
  def add_ext!(paths)
76
98
  exts = {
77
- params: "txt",
99
+ params: "env",
78
100
  vars: "rb",
79
101
  }
80
102
  ext = exts[@type.to_sym]
@@ -85,28 +107,28 @@ module Lono::Layering
85
107
  end
86
108
  end
87
109
 
88
- def full_layers(dir)
89
- layers = full_layering.map do |layer|
90
- "#{dir}/#{@type}/#{layer}"
91
- end
92
- if Lono.app
93
- app_layers = full_layering.map do |layer|
94
- "#{dir}/#{@type}/#{Lono.app}/#{layer}"
95
- end
96
- layers += app_layers
97
- end
98
- layers
99
- end
100
-
101
110
  @@shown_layers = {}
102
111
  def show_layers(paths)
103
112
  return if @@shown_layers[@type]
104
113
  logger.debug "#{@type.capitalize} Layers:"
114
+ show = Lono.config.layering.show || ENV['LONO_LAYERS']
105
115
  paths.each do |path|
106
- logger.debug " #{pretty_path(path)}" if File.exist?(path) || ENV['LONO_SHOW_ALL_LAYERS']
116
+ # next if path.include?("app/blueprints/") # more useful to show only config layers
117
+ if ENV['LONO_LAYERS_ALL']
118
+ logger.info " #{pretty_path(path)}"
119
+ elsif show
120
+ logger.info " #{pretty_path(path)}" if File.exist?(path)
121
+ end
107
122
  end
108
123
  logger.debug ""
109
124
  @@shown_layers[@type] = true
110
125
  end
126
+
127
+ def account
128
+ name = aws_data.account
129
+ # friendly name mapping
130
+ names = Lono.config.layering.names.stringify_keys
131
+ names[name] || name
132
+ end
111
133
  end
112
134
  end
data/lib/lono/names.rb CHANGED
@@ -21,30 +21,27 @@ module Lono
21
21
  vars.each do |var|
22
22
  string.gsub!(var, var_value(var))
23
23
  end
24
- strip(string)
24
+ cleanse(string)
25
25
  end
26
26
 
27
27
  def var_value(unexpanded)
28
28
  name = unexpanded.sub(':','').downcase
29
29
  if respond_to?(name)
30
- value = send(name).to_s
30
+ send(name).to_s # value
31
31
  else
32
32
  unexpanded
33
33
  end
34
34
  end
35
35
 
36
- def strip(string)
36
+ def cleanse(string)
37
37
  string.sub(/^-+/,'').sub(/-+$/,'') # remove leading and trailing -
38
38
  .gsub(%r{-+},'-') # remove double dashes are more. IE: -- => -
39
39
  .gsub('_','-') # underscores are not allowed in CloudFormation stack names
40
40
  end
41
41
 
42
- def app
43
- Lono.app
44
- end
45
-
46
- def env
47
- Lono.env
42
+ delegate :app, :role, :env, :extra, to: :lono
43
+ def lono
44
+ Lono
48
45
  end
49
46
  end
50
47
  end
@@ -1,10 +1,11 @@
1
1
  module Lono::S3
2
2
  class Bucket
3
+ extend Lono::AwsServices
4
+ extend Memoist
3
5
  include Lono::AwsServices
4
6
  include Lono::Cfn::Concerns
5
7
  include Lono::Utils::Logging
6
- extend Lono::AwsServices
7
- extend Memoist
8
+ include Lono::Utils::Sure
8
9
 
9
10
  STACK_NAME = ENV['LONO_STACK_NAME'] || "lono"
10
11
  def initialize(options={})
@@ -115,20 +116,12 @@ module Lono::S3
115
116
 
116
117
 
117
118
  def are_you_sure?
118
- return true if @options[:yes]
119
-
120
119
  if bucket_name.nil?
121
120
  logger.info "The lono stack and s3 bucket does not exist."
122
121
  exit
123
122
  end
124
123
 
125
- logger.info "Are you yes you want the lono bucket #{bucket_name.color(:green)} to be emptied and deleted? (y/N)"
126
- yes = $stdin.gets.strip
127
- confirmed = yes =~ /^Y/i
128
- unless confirmed
129
- logger.info "Phew that was close."
130
- exit
131
- end
124
+ sure?("Will empty and delete bucket #{bucket_name.color(:green)}. Are you sure?")
132
125
  end
133
126
 
134
127
  def template_body
@@ -145,6 +138,10 @@ module Lono::S3
145
138
  Tags:
146
139
  - Key: Name
147
140
  Value: lono
141
+ Outputs:
142
+ Bucket:
143
+ Value:
144
+ Ref: Bucket
148
145
  YAML
149
146
  end
150
147
 
@@ -166,6 +163,15 @@ module Lono::S3
166
163
  bucket = stack_resources.find { |r| r.logical_resource_id == "Bucket" }
167
164
  @@name = bucket.physical_resource_id # actual bucket name
168
165
  end
166
+
167
+ @@ensure_exist = false
168
+ def ensure_exist
169
+ return if @@ensure_exist
170
+ bucket = Lono::S3::Bucket.new
171
+ return if bucket.exist?
172
+ bucket.deploy
173
+ @@ensure_exist = true
174
+ end
169
175
  end
170
176
  end
171
177
  end