lono 8.0.0.pre.rc2 → 8.0.0.pre.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -2
  3. data/Gemfile +1 -3
  4. data/lib/lono/app/callable_option/concern.rb +12 -0
  5. data/lib/lono/app/callable_option.rb +56 -0
  6. data/lib/lono/app.rb +22 -23
  7. data/lib/lono/autoloader.rb +1 -0
  8. data/lib/lono/aws_services/helper.rb +0 -2
  9. data/lib/lono/blueprint.rb +1 -18
  10. data/lib/lono/builder/allow/base.rb +54 -0
  11. data/lib/lono/builder/allow/env.rb +17 -0
  12. data/lib/lono/builder/allow/region.rb +20 -0
  13. data/lib/lono/builder/allow.rb +8 -0
  14. data/lib/lono/builder/configset/combiner.rb +145 -0
  15. data/lib/lono/builder/configset/definition/base.rb +47 -0
  16. data/lib/lono/builder/configset/definition/context.rb +29 -0
  17. data/lib/lono/{configset/strategy/helpers/dsl → builder/configset/definition/dsl/syntax}/auth.rb +1 -1
  18. data/lib/lono/{configset/strategy/helpers/dsl/core.rb → builder/configset/definition/dsl/syntax/content.rb} +12 -4
  19. data/lib/lono/{configset/strategy/helpers/dsl/syntax.rb → builder/configset/definition/dsl/syntax/core.rb} +15 -9
  20. data/lib/lono/{configset/strategy/helpers/dsl → builder/configset/definition/dsl/syntax}/package.rb +1 -1
  21. data/lib/lono/builder/configset/definition/dsl/syntax.rb +5 -0
  22. data/lib/lono/{configset/strategy → builder/configset/definition}/dsl.rb +10 -14
  23. data/lib/lono/{configset/strategy → builder/configset/definition}/erb.rb +13 -16
  24. data/lib/lono/builder/configset/definition.rb +18 -0
  25. data/lib/lono/builder/configset/evaluator.rb +10 -0
  26. data/lib/lono/builder/configset/registration.rb +35 -0
  27. data/lib/lono/builder/context.rb +40 -0
  28. data/lib/lono/builder/dsl/evaluator.rb +6 -55
  29. data/lib/lono/builder/dsl/finalizer/base.rb +8 -0
  30. data/lib/lono/builder/dsl/finalizer/configsets.rb +7 -28
  31. data/lib/lono/builder/dsl/finalizer/files/base.rb +4 -0
  32. data/lib/lono/builder/dsl/finalizer/files/build.rb +58 -0
  33. data/lib/lono/builder/dsl/finalizer/files/replace.rb +31 -0
  34. data/lib/lono/builder/dsl/finalizer/files.rb +9 -0
  35. data/lib/lono/builder/dsl/finalizer/parameter_groups.rb +4 -3
  36. data/lib/lono/builder/dsl/finalizer.rb +4 -2
  37. data/lib/lono/builder/dsl/helpers/files.rb +7 -0
  38. data/lib/lono/builder/dsl/helpers/partials.rb +48 -53
  39. data/lib/lono/builder/dsl/helpers/s3.rb +1 -1
  40. data/lib/lono/builder/dsl/helpers/ssm/fetcher.rb +3 -1
  41. data/lib/lono/builder/dsl/helpers/template_file.rb +18 -6
  42. data/lib/lono/builder/dsl/helpers.rb +1 -11
  43. data/lib/lono/builder/dsl/syntax/core/resource/property_mover.rb +11 -1
  44. data/lib/lono/builder/dsl/syntax/core/squeezer.rb +16 -2
  45. data/lib/lono/builder/dsl.rb +1 -1
  46. data/lib/lono/builder/param.rb +4 -1
  47. data/lib/lono/builder/template/upload.rb +2 -15
  48. data/lib/lono/cfn/cancel.rb +5 -5
  49. data/lib/lono/cfn/deploy/iam.rb +1 -1
  50. data/lib/lono/cfn/deploy.rb +32 -3
  51. data/lib/lono/cfn/download.rb +0 -1
  52. data/lib/lono/cfn/plan/changeset.rb +2 -2
  53. data/lib/lono/cfn/plan/diff/data.rb +11 -1
  54. data/lib/lono/cfn/plan/param.rb +1 -1
  55. data/lib/lono/cfn/plan/template.rb +2 -2
  56. data/lib/lono/cfn/plan.rb +1 -0
  57. data/lib/lono/cli/abstract.rb +0 -6
  58. data/lib/lono/cli/base.rb +5 -3
  59. data/lib/lono/cli/build.rb +16 -60
  60. data/lib/lono/cli/clean.rb +3 -2
  61. data/lib/lono/cli/code.rb +12 -12
  62. data/lib/lono/cli/help/new/helper/blueprint.md +17 -0
  63. data/lib/lono/cli/help/new/helper/project.md +16 -0
  64. data/lib/lono/cli/list.rb +3 -6
  65. data/lib/lono/cli/new/blueprint.rb +3 -7
  66. data/lib/lono/cli/new/configset.rb +11 -44
  67. data/lib/lono/cli/new/helper/blueprint.rb +26 -0
  68. data/lib/lono/cli/new/helper/project.rb +24 -0
  69. data/lib/lono/cli/new/helper.rb +8 -27
  70. data/lib/lono/cli/new/sequence.rb +6 -1
  71. data/lib/lono/cli/new.rb +8 -12
  72. data/lib/lono/cli/status.rb +18 -0
  73. data/lib/lono/cli.rb +6 -9
  74. data/lib/lono/command.rb +0 -1
  75. data/lib/lono/component.rb +29 -0
  76. data/lib/lono/concerns/aws_info.rb +14 -0
  77. data/lib/lono/concerns/names.rb +9 -0
  78. data/lib/lono/configset.rb +17 -0
  79. data/lib/lono/core.rb +1 -1
  80. data/lib/lono/ext/bundler.rb +7 -0
  81. data/lib/lono/ext/core/module.rb +31 -0
  82. data/lib/lono/ext/core/object.rb +32 -0
  83. data/lib/lono/ext/core/string.rb +9 -0
  84. data/lib/lono/ext.rb +4 -0
  85. data/lib/lono/files/base.rb +12 -0
  86. data/lib/lono/files/builder.rb +37 -0
  87. data/lib/lono/files/compressor.rb +53 -0
  88. data/lib/lono/files/concerns/post_processing.rb +35 -0
  89. data/lib/lono/files/concerns/registration.rb +13 -0
  90. data/lib/lono/files/registry.rb +6 -0
  91. data/lib/lono/files.rb +37 -0
  92. data/lib/lono/importer/base.rb +1 -1
  93. data/lib/lono/inspector/summary.rb +0 -3
  94. data/lib/lono/layering/layer.rb +3 -17
  95. data/lib/lono/logger.rb +1 -3
  96. data/lib/lono/names.rb +1 -1
  97. data/lib/lono/s3/uploader.rb +29 -28
  98. data/lib/lono/seeder.rb +18 -27
  99. data/lib/lono/user_data.rb +3 -1
  100. data/lib/lono/version.rb +1 -1
  101. data/lib/lono/yamler/validator.rb +7 -22
  102. data/lib/lono.rb +8 -0
  103. data/lib/templates/configset/configset.rb +2 -16
  104. data/lib/templates/examples/configset/configset.rb +16 -0
  105. data/lib/templates/helper/%underscore_name%_helper.rb.tt +1 -1
  106. data/lono.gemspec +1 -1
  107. metadata +52 -39
  108. data/lib/lono/app_file/base.rb +0 -28
  109. data/lib/lono/app_file/build/lambda_layer/ruby_packager.rb +0 -153
  110. data/lib/lono/app_file/build/lambda_layer.rb +0 -20
  111. data/lib/lono/app_file/build.rb +0 -79
  112. data/lib/lono/app_file/registry/item.rb +0 -24
  113. data/lib/lono/app_file/registry.rb +0 -16
  114. data/lib/lono/app_file/upload.rb +0 -12
  115. data/lib/lono/builder/context/generic.rb +0 -11
  116. data/lib/lono/builder/context/loaders/load_files.rb +0 -23
  117. data/lib/lono/builder/context/loaders.rb +0 -35
  118. data/lib/lono/builder/context/params.rb +0 -6
  119. data/lib/lono/builder/context/template.rb +0 -4
  120. data/lib/lono/configset/builder.rb +0 -59
  121. data/lib/lono/configset/combiner.rb +0 -164
  122. data/lib/lono/configset/evaluate_file.rb +0 -8
  123. data/lib/lono/configset/meta/dsl.rb +0 -12
  124. data/lib/lono/configset/meta.rb +0 -19
  125. data/lib/lono/configset/s3_file/build.rb +0 -34
  126. data/lib/lono/configset/s3_file/item.rb +0 -38
  127. data/lib/lono/configset/s3_file/registry.rb +0 -12
  128. data/lib/lono/configset/s3_file/upload.rb +0 -12
  129. data/lib/lono/configset/strategy/base.rb +0 -83
  130. data/lib/lono/configset/strategy/helpers/dsl.rb +0 -8
  131. data/lib/lono/configset/strategy/helpers/erb.rb +0 -9
  132. data/lib/lono/lookup.rb +0 -12
  133. data/lib/lono/seeder/service_role.rb +0 -11
  134. data/lib/lono/utils/contexts.rb +0 -15
  135. data/lib/lono/utils/item/file_methods.rb +0 -29
  136. data/lib/lono/utils/item/zip.rb +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df8edbab23041858e8bea192749b440727066aeff707fa03edf5caf4dd529df9
4
- data.tar.gz: 22f1143dd996e18bd6801080128605db30957c324136ce277c493497adb1f3bb
3
+ metadata.gz: 99ed66c36726e513ebe394291384f039d6dbbc7beef5a376b28b3b84121f1a42
4
+ data.tar.gz: ec1902278f840c29539d54fffa9167565a27f1837a4ee2795d8db86badf0030d
5
5
  SHA512:
6
- metadata.gz: 866583abf80bbf971b345e23e1b54a430542ad4f5b0578e7973761c88065ba8875c3ef6f724a4291e8c16ff35163e461db0ee563eda438b11539b5f7d7fa2409
7
- data.tar.gz: 68e43613edfaa724c954541b4788a2365a0faa8e32d726ae84610255ad214b0d40c2ff84c830e8f44c73bbb9e00c9ab06708f614796f13738fcb7d2ca5f24056
6
+ metadata.gz: 522056fb098c360c2ad59d99dfabaa723aeec157ca5012938c36efcb130e1bf6c2974d158e3c2f864e258c5d4b065d8e949667291f6af7d779bad91d2b451a0f
7
+ data.tar.gz: 18d17bbf1fcdd0f9d7c59f87b83e463f277958fb34cfb07d5918904b76ae44ecd2995f7e36f09d0a99c15d01070b469abf44bcfc95ec8f413aa54fdb0058fc6c
data/CHANGELOG.md CHANGED
@@ -1,7 +1,20 @@
1
1
  # Change Log
2
2
 
3
- All notable changes to this project will be documented in this file.
4
- This project *tries* to adhere to [Semantic Versioning](http://semver.org/).
3
+ ## [8.0.0.rc3] - 2022-03-06
4
+
5
+ * lono files support for lambda functions
6
+ * new structure: remove Appfile
7
+ * allow regions and envs support
8
+ * print friend message with exact line of yaml code in case of aws
9
+ * cloudformation yaml validation error
10
+ * improve cli help
11
+ * configsets new structure
12
+ * lono new helper blueprint and project commands
13
+ * project helpers support
14
+ * include_modules improvements
15
+ * support vendor level helpers
16
+ * improve plan params diff
17
+ * lono plan build all first
5
18
 
6
19
  ## [8.0.0.rc2] - 2022-02-23
7
20
 
data/Gemfile CHANGED
@@ -3,8 +3,6 @@ source "https://rubygems.org"
3
3
  # Specify your gem dependencies in lono.gemspec
4
4
  gemspec
5
5
 
6
- if ENV['C9_USER']
7
- gem "rspec-lono", path: "~/boltops-tools/rspec-lono"
8
- else
6
+ group :test do
9
7
  gem "rspec-lono", git: "https://github.com/boltops-tools/rspec-lono", branch: "master"
10
8
  end
@@ -0,0 +1,12 @@
1
+ class Lono::App::CallableOption
2
+ module Concern
3
+ def callable_option(options={})
4
+ callable_option = Lono::App::CallableOption.new(
5
+ config_name: options[:config_name],
6
+ config_value: options[:config_value],
7
+ passed_args: options[:passed_args],
8
+ )
9
+ callable_option.object
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,56 @@
1
+ # Class represents a lono option that is possibly callable. Examples:
2
+ #
3
+ # config.allow.envs
4
+ # config.allow.regions
5
+ # config.deny.envs
6
+ # config.deny.regions
7
+ #
8
+ # Abstraction is definitely obtuse. Using it to get rid of duplication.
9
+ #
10
+ class Lono::App
11
+ class CallableOption
12
+ include Lono::Utils::Logging
13
+
14
+ def initialize(options={})
15
+ @options = options
16
+ # Example:
17
+ # config_name: config.allow.envs
18
+ # config_value: ["dev"]
19
+ # args: [@stack_name] # passed to object.call
20
+ @config_name = options[:config_name]
21
+ @config_value = options[:config_value]
22
+ @passed_args = options[:passed_args]
23
+ end
24
+
25
+ # Returns either an Array or nil
26
+ def object
27
+ case @config_value
28
+ when nil
29
+ return nil
30
+ when Array
31
+ return @config_value
32
+ when -> (c) { c.respond_to?(:public_instance_methods) && c.public_instance_methods.include?(:call) }
33
+ object= @config_value.new
34
+ when -> (c) { c.respond_to?(:call) }
35
+ object = @config_value
36
+ else
37
+ raise "Invalid option for #{@config_name}"
38
+ end
39
+
40
+ if object
41
+ result = @passed_args.empty? ? object.call : object.call(*@passed_args)
42
+ unless result.is_a?(Array) || result.is_a?(NilClass)
43
+ message = "ERROR: The #{@config_name} needs to return an Array or nil"
44
+ logger.info message.color(:yellow)
45
+ logger.info <<~EOL
46
+ The #{@config_name} when assigned a class, object, or proc must implement
47
+ the call method and return an Array or nil.
48
+ The current return value is a #{result.class}
49
+ EOL
50
+ raise message
51
+ end
52
+ end
53
+ result
54
+ end
55
+ end
56
+ end
data/lib/lono/app.rb CHANGED
@@ -13,6 +13,16 @@ module Lono
13
13
  def defaults
14
14
  config = ActiveSupport::OrderedOptions.new
15
15
 
16
+ config.allow = ActiveSupport::OrderedOptions.new
17
+ config.allow.envs = nil
18
+ config.allow.regions = nil
19
+ config.deny = ActiveSupport::OrderedOptions.new
20
+ config.deny.envs = nil
21
+ config.deny.regions = nil
22
+
23
+ config.layering = ActiveSupport::OrderedOptions.new
24
+ config.layering.names = {}
25
+
16
26
  config.log = ActiveSupport::OrderedOptions.new
17
27
  config.log.root = Lono.log_root
18
28
  config.logger = lono_logger
@@ -20,16 +30,21 @@ module Lono
20
30
  config.logger.level = ENV['LONO_LOG_LEVEL'] || :info
21
31
 
22
32
  config.names = ActiveSupport::OrderedOptions.new
23
- config.names.stack = ":APP-:BLUEPRINT-:ENV"
24
33
  config.names.output = ActiveSupport::OrderedOptions.new
25
- config.names.output.stack = ":BLUEPRINT-:ENV" # does not include APP by default. Think this is more common
26
34
  config.names.output.expand = true
35
+ config.names.output.stack = ":BLUEPRINT-:ENV" # does not include APP by default. Think this is more common
36
+ config.names.stack = ":APP-:BLUEPRINT-:ENV"
37
+
38
+ config.plan = ActiveSupport::OrderedOptions.new
39
+ config.plan.changeset = true
40
+ config.plan.params = "full"
41
+ config.plan.template = "summary" # summary is same as true
27
42
 
28
- config.paths = ActiveSupport::OrderedOptions.new
29
- config.paths.scripts = "scripts"
30
- config.paths.content = "content"
31
- config.paths.helpers = "helpers"
32
- config.paths.user_data = "user_data"
43
+ config.seed = ActiveSupport::OrderedOptions.new
44
+ config.seed.where = "config"
45
+
46
+ config.test = ActiveSupport::OrderedOptions.new
47
+ config.test.framework = "rspec"
33
48
 
34
49
  config.up = ActiveSupport::OrderedOptions.new
35
50
  config.up.capabilities = nil
@@ -37,22 +52,6 @@ module Lono
37
52
  config.up.rollback = true
38
53
  config.up.tags = nil
39
54
 
40
- config.diff = ActiveSupport::OrderedOptions.new
41
- config.diff.changeset = true
42
- config.diff.params = "full"
43
- config.diff.template = "summary" # summary is same as true
44
-
45
- config.extract_scripts = {}
46
-
47
- config.test = ActiveSupport::OrderedOptions.new
48
- config.test.framework = "rspec"
49
-
50
- config.layering = ActiveSupport::OrderedOptions.new
51
- config.layering.names = {}
52
-
53
- config.seed = ActiveSupport::OrderedOptions.new
54
- config.seed.where = "config"
55
-
56
55
  config
57
56
  end
58
57
 
@@ -17,6 +17,7 @@ module Lono
17
17
  loader.inflector = Inflector.new
18
18
  loader.push_dir(File.dirname(__dir__)) # lib
19
19
  loader.log! if ENV["LONO_AUTOLOAD_LOG"]
20
+ loader.ignore("#{__dir__}/ext.rb")
20
21
  loader.setup
21
22
  end
22
23
  end
@@ -1,8 +1,6 @@
1
1
  module Lono::AwsServices
2
2
  module Helper
3
3
  def stack_exists?(stack_name)
4
- return false if ENV['LONO_NOOP']
5
-
6
4
  exist = nil
7
5
  begin
8
6
  # When the stack does not exist an exception is raised. Example:
@@ -1,22 +1,5 @@
1
1
  module Lono
2
- class Blueprint
3
- attr_reader :name
4
- def initialize(options={})
5
- @options = options
6
- @name = options[:blueprint]
7
- end
8
-
9
- def exist?
10
- !root.nil?
11
- end
12
-
13
- def root
14
- paths = Dir.glob("#{Lono.root}/{app,vendor}/blueprints/*")
15
- paths.find do |path|
16
- path.include?("blueprints/#{@name}")
17
- end
18
- end
19
-
2
+ class Blueprint < Component
20
3
  def output_path
21
4
  "#{Lono.root}/output/#{@name}/template.yml"
22
5
  end
@@ -0,0 +1,54 @@
1
+ class Lono::Builder::Allow
2
+ class Base < Lono::CLI::Base
3
+ include Lono::App::CallableOption::Concern
4
+
5
+ def check!
6
+ messages = []
7
+ unless allowed?
8
+ messages << message # message is interface method
9
+ end
10
+ unless messages.empty?
11
+ puts "ERROR: The configs do not allow this.".color(:red)
12
+ puts messages
13
+ exit 1
14
+ end
15
+ end
16
+
17
+ def allowed?
18
+ if allows.nil? && denys.nil?
19
+ true
20
+ elsif denys.nil?
21
+ allows.include?(check_value)
22
+ elsif allows.nil?
23
+ !denys.include?(check_value)
24
+ else
25
+ allows.include?(check_value) && !denys.include?(check_value)
26
+ end
27
+ end
28
+
29
+ def allows
30
+ callable_option(
31
+ config_name: "config.allow.#{config_name}",
32
+ config_value: config.dig(:allow, config_name),
33
+ passed_args: [@blueprint],
34
+ )
35
+ end
36
+
37
+ def denys
38
+ callable_option(
39
+ config_name: "config.deny.#{config_name}",
40
+ config_value: config.dig(:deny, config_name),
41
+ passed_args: [@blueprint],
42
+ )
43
+ end
44
+
45
+ private
46
+ def config
47
+ Lono.config
48
+ end
49
+
50
+ def config_name
51
+ self.class.to_s.split('::').last.underscore.pluralize.to_sym # ActiveSuport::HashWithIndifferentAccess#dig requires symbol
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,17 @@
1
+ class Lono::Builder::Allow
2
+ class Env < Base
3
+ # interface method
4
+ def message
5
+ messages = []
6
+ messages << "This env is not allowed to be used: LONO_ENV=#{Lono.env}"
7
+ messages << "Allow envs: #{allows.join(', ')}" if allows
8
+ messages << "Deny envs: #{denys.join(', ')}" if denys
9
+ messages.join("\n")
10
+ end
11
+
12
+ # interface method
13
+ def check_value
14
+ Lono.env
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ class Lono::Builder::Allow
2
+ class Region < Base
3
+ include Lono::Concerns::AwsInfo
4
+
5
+ # interface method
6
+ def message
7
+ messages = []
8
+ word = config_name.to_s # IE: regions or locations
9
+ messages << "This #{word.singularize} is not allowed to be used: Detected current #{word.singularize}=#{current_region}"
10
+ messages << "Allow #{word}: #{allows.join(', ')}" if allows
11
+ messages << "Deny #{word}: #{denys.join(', ')}" if denys
12
+ messages.join("\n")
13
+ end
14
+
15
+ # interface method
16
+ def check_value
17
+ region
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ module Lono::Builder
2
+ class Allow < Lono::CLI::Base
3
+ def check!
4
+ Env.new(@options).check!
5
+ Region.new(@options).check!
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,145 @@
1
+ module Lono::Builder::Configset
2
+ class Combiner < Lono::CLI::Base
3
+ def initialize(options={})
4
+ super
5
+ @cfn = options[:cfn] # merge from Dsl::Finalizer::Configsets#run
6
+ @metas = options[:metas] # merge from Configset::Evaluator#evaluate
7
+ @configsets = []
8
+ @map = {} # stores resource logical id => metadata cfn-init
9
+ end
10
+
11
+ # Returns metadata map structure
12
+ #
13
+ # {"Instance"=>
14
+ # {"Metadata"=>
15
+ # {"AWS::CloudFormation::Init"=>
16
+ #
17
+ def combine
18
+ return @map if metas_empty?
19
+ add_existing
20
+ add_built
21
+ build_map # metadata map
22
+ end
23
+
24
+ def metas_empty?
25
+ @metas.empty?
26
+ end
27
+
28
+ def add_existing
29
+ existing_configsets.each do |configset|
30
+ add(configset)
31
+ end
32
+ end
33
+
34
+ def add_built
35
+ @metas.each do |meta|
36
+ definition = Definition.new(@options.merge(meta: meta))
37
+ configset = definition.evaluate
38
+ add(configset)
39
+ end
40
+ end
41
+
42
+ # Useful for specs
43
+ def add(configset)
44
+ found = @configsets.detect { |c| c.name == configset.name && c.resource == configset.resource }
45
+ @configsets << configset unless found
46
+ end
47
+
48
+ # Each metadata has this structure:
49
+ #
50
+ # {"Metadata"=>
51
+ # {"AWS::CloudFormation::Init"=>
52
+ # {"configSets"=>{"default"=>["aaa1", "aaa2"]},
53
+ # "aaa1"=>{"commands"=>{"test"=>{"command"=>"echo from-aaa1 > test1.txt"}}},
54
+ # "aaa2"=>
55
+ # {"commands"=>{"test"=>{"command"=>"echo from-aaa2 > test1.txt"}}}}}}
56
+ #
57
+ def build_map
58
+ metadata_map = {}
59
+ configsets_map = {}
60
+
61
+ @configsets.each_with_index do |configset, i|
62
+ padded_i = "%03d" % i
63
+
64
+ name, resource, metadata = configset.name, configset.resource, configset.metadata
65
+ configsets = configsets_map[resource] ||= {}
66
+
67
+ validate_structure!(name, metadata)
68
+
69
+ new_metadata = metadata["Metadata"].dup
70
+ init = new_metadata["AWS::CloudFormation::Init"] # important: adjust data by reference
71
+
72
+ if init.key?("configSets")
73
+ # validate_simple!(name, new_metadata["AWS::CloudFormation::Init"]["configSets"]) # validate original configset for only simple elements
74
+
75
+ # 1. expand each config as its own config, flattening to top-level
76
+ cs = init.delete("configSets") # Only support configSets with simple Array of Strings
77
+ new_config_set = {}
78
+ new_config_set[name] = cs["default"].map {|c| "#{padded_i}_#{c}" }
79
+ init.transform_keys! { |c| "#{padded_i}_#{c}" }
80
+
81
+ # Rebuild default configSet, append the new complex ConfigSet structure with each iteration
82
+ configsets["default"] ||= []
83
+ configsets["default"] << {"ConfigSet" => name}
84
+ configsets.merge!(new_config_set) # add each config from #1 to the top-level
85
+
86
+ init["configSets"] = configsets # replace new configset
87
+ else # simple config
88
+ init["configSets"] = configsets # adjust data by reference
89
+ configsets["default"] ||= []
90
+ configsets["default"] << {"ConfigSet" => name}
91
+
92
+ # build new config
93
+ config_key = "#{padded_i}_single_generated"
94
+ configsets[name] = [config_key]
95
+ new_config = {config_key => init["config"]}
96
+ # replace old config with new one
97
+ init.delete("config") # delete original simple config
98
+ init.merge!(new_config)
99
+ end
100
+
101
+ metadata_map[resource] ||= {"Metadata" => {}}
102
+ metadata_map[resource]["Metadata"].deep_merge!(new_metadata)
103
+ @map[resource] = metadata_map[resource]
104
+ end
105
+ @map
106
+ end
107
+
108
+ # Normalized/convert cfn template to mimic the registry format
109
+ def existing_configsets
110
+ configsets = []
111
+ @cfn["Resources"].each do |logical_id, attributes|
112
+ cloudformation_init = attributes.dig("Metadata", "AWS::CloudFormation::Init")
113
+ next unless cloudformation_init
114
+
115
+ configset = Lono::Configset.new(name: "#{logical_id}OriginalConfigset", resource: logical_id)
116
+ configset.metadata = {"Metadata" => attributes["Metadata"]} # wrap metadata to create right structure
117
+ configsets << configset
118
+ end
119
+ configsets
120
+ end
121
+
122
+ def validate_structure!(name, metadata)
123
+ return if metadata.is_a?(Hash) && metadata.dig("Metadata", "AWS::CloudFormation::Init")
124
+
125
+ puts "ERROR: The #{name} configset does not appear to have a AWS::CloudFormation::Init key".color(:red)
126
+ puts "Please double check the #{name} configset.yml structure"
127
+ exit 1
128
+ end
129
+
130
+ def validate_simple!(name, cs)
131
+ has_complex_type = cs["default"].detect { |s| !s.is_a?(String) }
132
+ return unless has_complex_type
133
+ message =<<~EOL
134
+ ERROR: The configset #{name} has a configSets property with a complex type.
135
+ configSets:
136
+
137
+ #{cs}
138
+
139
+ lono configsets only supports combining configSets with an Array of Strings.
140
+ EOL
141
+ puts message.color(:red)
142
+ exit 1
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,47 @@
1
+ class Lono::Builder::Configset::Definition
2
+ class Base < Lono::CLI::Base
3
+ include DslEvaluator
4
+ include Lono::Builder::Dsl::Syntax
5
+ include Lono::Utils::Pretty
6
+ include Context
7
+
8
+ # Really only use @path in Configset DSL and ERB evaluation.
9
+ # However, configsets are built within the CloudFormation template and can use
10
+ # things instrinic functions like `ref` like would normally have access to.
11
+ # So configsets need the same context
12
+ #
13
+ # Configset::Definition::Base < Lono::CLI::Base
14
+ #
15
+ # for
16
+ #
17
+ # include Lono::Builder::Dsl::Syntax
18
+ #
19
+ def initialize(options={})
20
+ super
21
+ @meta = @options[:meta]
22
+ @configset = Lono::Configset.new(@meta)
23
+ expose_instance_variables
24
+ end
25
+
26
+ # This context is used by the DSL evaluation. Expose variables so user can use them in configset definitions.
27
+ # Example:
28
+ #
29
+ # "/etc/cfn/hooks.d/cfn-auto-reloader.conf":
30
+ # content:
31
+ # Fn::Sub:
32
+ # ...
33
+ # path=Resources.<%= @resource %>.Metadata.AWS::CloudFormation::Init
34
+ #
35
+ def expose_instance_variables
36
+ @name = @meta[:name]
37
+ @resource = @meta[:resource]
38
+ end
39
+
40
+ def wrap_with_metadata(cloudformation_init)
41
+ full = {"Metadata" => {}}
42
+ full["Metadata"]["AWS::CloudFormation::Init"] = cloudformation_init["AWS::CloudFormation::Init"]
43
+ full["Metadata"]["AWS::CloudFormation::Authentication"] = authentication if authentication # only on dsl
44
+ full.deep_stringify_keys.dup # metadata
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,29 @@
1
+ class Lono::Builder::Configset::Definition
2
+ module Context
3
+ include DslEvaluator
4
+
5
+ def load_context
6
+ load_vars
7
+ load_helpers
8
+ end
9
+
10
+ # Docs: https://lono.cloud/docs/configsets/layering/
11
+ # Layering is simple enough to keep in this method.
12
+ def load_vars
13
+ logger.debug "Layers for configset #{@configset.name}:"
14
+ evaluate_layer("#{@configset.root}/vars.rb") # source defaults
15
+ evaluate_layer("#{Lono.root}/config/configsets/#{@configset.name}/vars.rb") # source overrides
16
+ evaluate_layer("#{@blueprint.root}/config/configsets/vars/#{@configset.name}.rb") # blueprint overrides
17
+ evaluate_layer("#{Lono.root}/config/blueprints/#{@blueprint.name}/configsets/vars/#{@configset.name}.rb") # user overrides
18
+ end
19
+
20
+ def evaluate_layer(path)
21
+ logger.debug " #{pretty_path(path)}" if File.exist?(path) || ENV['LONO_SHOW_ALL_LAYERS']
22
+ evaluate_file(path)
23
+ end
24
+
25
+ def load_helpers
26
+ load_helper_files("#{@configset.root}/helpers", type: :configset)
27
+ end
28
+ end
29
+ end
@@ -1,4 +1,4 @@
1
- module Lono::Configset::Strategy::Helpers::Dsl
1
+ module Lono::Builder::Configset::Definition::Dsl::Syntax
2
2
  module Auth
3
3
  def authentication(data=nil, force: false)
4
4
  if data.nil?
@@ -1,7 +1,7 @@
1
- module Lono::Configset::Strategy::Helpers::Dsl
2
- module Core
1
+ module Lono::Builder::Configset::Definition::Dsl::Syntax
2
+ module Content
3
3
  def content_file(path)
4
- content_path = "#{@root}/lib/content"
4
+ content_path = "#{file_root}/content"
5
5
  file = "#{content_path}/#{path}"
6
6
  if File.exist?(file)
7
7
  IO.read(file)
@@ -10,8 +10,16 @@ module Lono::Configset::Strategy::Helpers::Dsl
10
10
  end
11
11
  end
12
12
 
13
+ def file_root
14
+ if @configset
15
+ @configset.root
16
+ else
17
+ @blueprint.root
18
+ end
19
+ end
20
+
13
21
  def s3_key(name)
14
- Lono::Configset::S3File::Registry.register(name, blueprint: @blueprint.name, configset: @configset, root: @root)
22
+ Lono::Configset::S3File::Registry.register(name, blueprint: @blueprint, configset: @configset, root: @root)
15
23
  "file://configset/#{@configset}/#{name}"
16
24
  end
17
25
  end
@@ -1,7 +1,20 @@
1
- module Lono::Configset::Strategy::Helpers::Dsl
2
- module Syntax
1
+ module Lono::Builder::Configset::Definition::Dsl::Syntax
2
+ module Core
3
3
  extend Memoist
4
4
 
5
+ #
6
+ # The configset method is different with configset registration vs configset definition
7
+ #
8
+ # definition: app/configsets/httpd/configset.rb
9
+ # registration: app/blueprints/demo/configsets.rb
10
+ #
11
+ def configset(current)
12
+ @tracked << current
13
+ previous, @current = @current, current
14
+ yield
15
+ @current = previous
16
+ end
17
+
5
18
  %w[package group user file service].each do |meth|
6
19
  section = meth.pluralize
7
20
  define_method(meth) do |k, props={}|
@@ -53,13 +66,6 @@ module Lono::Configset::Strategy::Helpers::Dsl
53
66
  current_structure(@current)["sources"].deep_merge!(item)
54
67
  end
55
68
 
56
- def configset(current)
57
- @tracked << current
58
- previous, @current = @current, current
59
- yield
60
- @current = previous
61
- end
62
-
63
69
  private
64
70
  def current_structure(configset)
65
71
  @structure[configset] ||= {}
@@ -1,4 +1,4 @@
1
- module Lono::Configset::Strategy::Helpers::Dsl
1
+ module Lono::Builder::Configset::Definition::Dsl::Syntax
2
2
  module Package
3
3
  # In recent versions of the AmazonLinux2 cfnbootstrap, , the package command doesnt work with updated versions of rubygems.
4
4
  # Get this error
@@ -0,0 +1,5 @@
1
+ class Lono::Builder::Configset::Definition::Dsl
2
+ module Syntax
3
+ include_modules "syntax"
4
+ end
5
+ end