lono 7.0.5 → 7.1.0

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/lib/lono.rb +1 -1
  4. data/lib/lono/blueprint/meta.rb +3 -3
  5. data/lib/lono/cfn/base.rb +5 -3
  6. data/lib/lono/configset.rb +7 -0
  7. data/lib/lono/configset/combiner.rb +11 -4
  8. data/lib/lono/configset/generator.rb +52 -0
  9. data/lib/lono/configset/materializer/gems_builder.rb +1 -1
  10. data/lib/lono/configset/new.rb +2 -2
  11. data/lib/lono/configset/register/project.rb +4 -3
  12. data/lib/lono/configset/strategy/base.rb +63 -0
  13. data/lib/lono/configset/strategy/dsl.rb +26 -0
  14. data/lib/lono/configset/strategy/dsl/helpers.rb +4 -0
  15. data/lib/lono/configset/strategy/dsl/syntax.rb +32 -0
  16. data/lib/lono/configset/strategy/erb.rb +30 -0
  17. data/lib/lono/configset/{loader/dsl.rb → strategy/erb/helpers.rb} +2 -2
  18. data/lib/lono/conventions.rb +1 -0
  19. data/lib/lono/finder/base.rb +1 -1
  20. data/lib/lono/importer/base.rb +0 -11
  21. data/lib/lono/jade.rb +1 -1
  22. data/lib/lono/jadespec.rb +15 -4
  23. data/lib/lono/{config_location.rb → layering.rb} +30 -46
  24. data/lib/lono/opts.rb +2 -0
  25. data/lib/lono/param/generator.rb +27 -99
  26. data/lib/lono/sets/instances/sync.rb +8 -10
  27. data/lib/lono/template/context/loader.rb +7 -6
  28. data/lib/lono/template/generator.rb +6 -6
  29. data/lib/lono/version.rb +1 -1
  30. data/lib/templates/blueprint/%blueprint_name%.gemspec.tt +6 -4
  31. data/lib/templates/configset/%configset_name%.gemspec.tt +3 -1
  32. data/lib/templates/configset/.gitignore +1 -0
  33. data/lib/templates/configset/lib/configset.rb +16 -0
  34. data/lono.gemspec +1 -0
  35. metadata +25 -6
  36. data/lib/lono/configset/loader.rb +0 -98
  37. data/lib/templates/configset/lib/configset.yml +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 978e40e7263ef0cc011601eec42c5581e580c4bc7c74feea55658776d2f60f61
4
- data.tar.gz: b8ef03d604d0145577c58a9b2aef532d7e0ac033145bba7b56e5182314f2fef6
3
+ metadata.gz: 6c82050fbf233130f2fda69d2bc32fe20d8887a1d32658875522cc11a8cc3df6
4
+ data.tar.gz: 0e5a9f4657820d9104410ba5b35c3c2383a2967c5b3145f03ea9927a4413eb12
5
5
  SHA512:
6
- metadata.gz: 6df32378a05c9d8279cafb2f6e379b39bfdc3aba799371c1fafd7318fcd1d68aed09f75a01817723b3de2852917d3e7ac9b1c5cec86a2617aa19d56a814a82ab
7
- data.tar.gz: 02c7f8fc999daecb2a87889123ce49ced93cc72bdbf0ff2e6b9d1880ea40fa2e8d5d565229d941dee0c746d829f5dd841fc084f41aa42f04392386214d35a722
6
+ metadata.gz: 4fa72e2ed20267512962e1b4ff0cab8962186fd8bb0b1be9a07e478577aaeedae7ec4cded6e1bee7c1c77bffe1a93ad126e3a60601ff0fe1381fea30ccb15fb8
7
+ data.tar.gz: e0388dd38dbbae9483088d07bb630585b779b167f3cdae4f36b861e72cc5c24a8ba39797fabb4296da8550d73b1277459645a1972564f9e4baffee40d08d51b7
data/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [7.1.0]
7
+ - #42 introduce configset dsl
8
+ - #43 improve layering behavior
9
+ - #44 metadata fixes: lono_strategy
10
+ - #45 lono_type fix
11
+ - #46 require bundler 2 at least: fixes Gemfile.lock generation
12
+ - #47 use with_unbundled_env
13
+
6
14
  ## [7.0.5]
7
15
  - #41 sort parameter with required at top
8
16
 
data/lib/lono.rb CHANGED
@@ -3,6 +3,7 @@ $stdout.sync = true unless ENV["LONO_STDOUT_SYNC"] == "0"
3
3
  require "active_support/core_ext/class"
4
4
  require 'active_support/core_ext/hash'
5
5
  require 'active_support/core_ext/string'
6
+ require 'cfn_camelizer'
6
7
  require 'fileutils'
7
8
  require 'json'
8
9
  require 'memoist'
@@ -10,7 +11,6 @@ require 'plissken'
10
11
  require 'rainbow/ext/string'
11
12
  require 'render_me_pretty'
12
13
  require 'yaml'
13
- require 'cfn_camelizer'
14
14
 
15
15
  gem_root = File.dirname(__dir__)
16
16
  $:.unshift("#{gem_root}/lib")
@@ -8,13 +8,13 @@ class Lono::Blueprint
8
8
  @blueprint = blueprint
9
9
  end
10
10
 
11
- def config
11
+ def jadespec
12
12
  Lono::Finder::Blueprint.find(@blueprint)
13
13
  end
14
- memoize :config
14
+ memoize :jadespec
15
15
 
16
16
  def auto_camelize?(target_section)
17
- auto_camelize = config.auto_camelize
17
+ auto_camelize = jadespec.auto_camelize
18
18
  # auto_camelize.nil? for backward compatibility
19
19
  return true if auto_camelize.nil? || auto_camelize == true
20
20
 
data/lib/lono/cfn/base.rb CHANGED
@@ -151,7 +151,7 @@ class Lono::Cfn
151
151
  def stack_status
152
152
  return true if testing_update?
153
153
  return false if @options[:noop]
154
- resp = cfn.describe_stacks(stack_name: @stack_name)
154
+ resp = cfn.describe_stacks(stack_name: @stack)
155
155
  resp.stacks[0].stack_status
156
156
  end
157
157
 
@@ -169,8 +169,10 @@ class Lono::Cfn
169
169
 
170
170
  def show_options(options, meth=nil)
171
171
  options = options.clone.compact
172
- options[:template_body] = "Hidden due to size... View at: #{pretty_path(template_path)}"
173
- options[:template_url] = options[:template_url].sub(/\?.*/,'')
172
+ if options[:template_body] # continue_update_rollback
173
+ options[:template_body] = "Hidden due to size... View at: #{pretty_path(template_path)}"
174
+ options[:template_url] = options[:template_url].sub(/\?.*/,'')
175
+ end
174
176
  to = meth || "AWS API"
175
177
  puts "Parameters passed to #{to}:"
176
178
  puts YAML.dump(options.deep_stringify_keys)
@@ -5,5 +5,12 @@ module Lono
5
5
  option(*args)
6
6
  end
7
7
  register(New, "new", "new NAME", "Generates new lono configset.")
8
+
9
+ desc "generate", "Generate configset from DSL"
10
+ long_desc Help.text(:generate)
11
+ option :resource, default: "PretendResource", desc: "Set the @resource instance variable availalbe in the configset"
12
+ def generate(configset)
13
+ Generator.new(options.merge(configset: configset)).run
14
+ end
8
15
  end
9
16
  end
@@ -9,6 +9,11 @@ class Lono::Configset
9
9
  @map = {} # stores resource logical id => metadata cfn-init
10
10
  end
11
11
 
12
+ def generator_options(registry, options={})
13
+ o = @options.merge(configset: registry.name, resource: registry.resource)
14
+ o.merge(options)
15
+ end
16
+
12
17
  def metadata_map
13
18
  return {} unless additional_configsets?
14
19
 
@@ -17,12 +22,14 @@ class Lono::Configset
17
22
  end
18
23
 
19
24
  Register::Blueprint.configsets.each do |registry|
20
- loader = Lono::Blueprint::Configset::Loader.new(registry, @options)
21
- add(registry, loader.metdata_configset)
25
+ generator = Lono::Configset::Generator.new(generator_options(registry, type: "blueprint"))
26
+ cloudformation_init = generator.build
27
+ add(registry, cloudformation_init)
22
28
  end
23
29
  Register::Project.configsets.each do |registry|
24
- loader = Loader.new(registry, @options)
25
- add(registry, loader.metdata_configset)
30
+ generator = Lono::Configset::Generator.new(generator_options(registry, type: "project"))
31
+ cloudformation_init = generator.build
32
+ add(registry, cloudformation_init)
26
33
  end
27
34
 
28
35
  combine
@@ -0,0 +1,52 @@
1
+ class Lono::Configset
2
+ class Generator
3
+ def initialize(options)
4
+ @options = options
5
+ @configset = options[:configset]
6
+ @type = options[:type] || "project"
7
+ end
8
+
9
+ def run
10
+ check_configset_exist!
11
+ structure = build
12
+ puts YAML.dump(structure)
13
+ end
14
+
15
+ def check_configset_exist!
16
+ exist = !!Lono::Finder::Configset.find(@configset)
17
+ unless exist
18
+ puts "configset #{@configset.color(:green)} not found."
19
+ exit 1
20
+ end
21
+ end
22
+
23
+ def build
24
+ # Examples:
25
+ # Erb.new(options).build
26
+ # Dsl.new(options).build
27
+ generator_class = "Lono::Configset::Strategy::#{strategy.camelize}"
28
+ generator_class = Object.const_get(generator_class)
29
+ generator_class.new(@options.merge(root: configset_root)).build
30
+ end
31
+
32
+ def strategy
33
+ jadespec = Lono::Jadespec.new(configset_root, "unknown") # abusing Jadespec to get strategy
34
+ jadespec.lono_strategy
35
+ end
36
+
37
+ def configset_root
38
+ finder = finder_class.new
39
+ found = finder.find(@configset, local_only: false)
40
+ found.root if found
41
+ end
42
+
43
+ def finder_class
44
+ case @type
45
+ when "project"
46
+ Lono::Finder::Configset
47
+ when "blueprint"
48
+ Lono::Finder::Blueprint::Configset
49
+ end
50
+ end
51
+ end
52
+ end
@@ -33,7 +33,7 @@ module Lono::Configset::Materializer
33
33
  end
34
34
 
35
35
  def bundle
36
- Bundler.with_original_env do
36
+ Bundler.with_unbundled_env do
37
37
  bundle_install
38
38
  end
39
39
  end
@@ -35,8 +35,8 @@ class Lono::Configset
35
35
  if @demo
36
36
  options = {}
37
37
  else
38
- create_file "#{@cwd}/#{configset_name}/lib/configset.yml"
39
- options = {exclude_pattern: %r{configset\.yml}}
38
+ create_file "#{@cwd}/#{configset_name}/lib/configset.rb"
39
+ options = {exclude_pattern: %r{configset\.rb}}
40
40
  end
41
41
 
42
42
  directory ".", "#{@cwd}/#{configset_name}", options
@@ -4,9 +4,10 @@ module Lono::Configset::Register
4
4
  self.validations = []
5
5
 
6
6
  def evaluate
7
- location = Lono::ConfigLocation.new("configsets", @options, Lono.env)
8
- evaluate_file(location.lookup_base) if location.lookup_base
9
- evaluate_file(location.lookup) if location.lookup # config file
7
+ layering = Lono::Layering.new("configsets", @options, Lono.env)
8
+ layering.locations.each do |path|
9
+ evaluate_file(path)
10
+ end
10
11
  end
11
12
  end
12
13
  end
@@ -0,0 +1,63 @@
1
+ # Subclasses must implement:
2
+ #
3
+ # find_evaluation_path - use to set @evaluation_path
4
+ # load
5
+ #
6
+ # Notable instance variables:
7
+ #
8
+ # @evaluation_path - IE: lib/configset.rb or lib/configset.yml
9
+ # @root - IE: /path/to/root/of/configset
10
+ #
11
+ module Lono::Configset::Strategy
12
+ class Base
13
+ extend Memoist
14
+ include Lono::Configset::EvaluateFile
15
+
16
+ def initialize(options={})
17
+ @options = options
18
+ @configset = options[:configset]
19
+ @root = options[:root]
20
+ @resource = options[:resource] || "FakeResource"
21
+ @blueprint = Lono::Conventions.new(options).blueprint
22
+ end
23
+
24
+ def build
25
+ @evaluation_path = find_evaluation_path # implemented by subclass
26
+ copy_instance_variables
27
+ load_configset_helpers
28
+ load # implemented by subclass
29
+ end
30
+ memoize :build
31
+
32
+ def copy_instance_variables
33
+ load_blueprint_predefined_variables
34
+ load_project_predefined_variables
35
+ end
36
+
37
+ def load_blueprint_predefined_variables
38
+ evaluate_file("#{@root}/lib/variables.rb")
39
+ end
40
+
41
+ def load_project_predefined_variables
42
+ paths = [
43
+ "#{Lono.root}/configs/#{@blueprint}/configsets/variables.rb", # global
44
+ "#{Lono.root}/configs/#{@blueprint}/configsets/#{@configset}/variables.rb", # configset specific
45
+ ]
46
+ paths.each do |path|
47
+ evaluate_file(path)
48
+ end
49
+ end
50
+
51
+ def load_configset_helpers
52
+ paths = Dir.glob("#{@root}/lib/helpers/**/*.rb")
53
+ paths.sort_by! { |p| p.size } # load possible namespaces first
54
+ paths.each do |path|
55
+ filename = path.sub(%r{.*/lib/helpers/},'').sub('.rb','')
56
+ module_name = filename.camelize
57
+
58
+ require path
59
+ self.class.send :include, module_name.constantize
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,26 @@
1
+ module Lono::Configset::Strategy
2
+ class Dsl < Base
3
+ include Helpers
4
+ include Syntax
5
+
6
+ def initialize(options={})
7
+ super
8
+ @structure = {} # holds in memory the configset hash structure
9
+ @current = "main" # current configset
10
+ @tracked = []
11
+ end
12
+
13
+ def find_evaluation_path
14
+ "#{@root}/lib/configset.rb"
15
+ end
16
+
17
+ def load
18
+ evaluate_file(@evaluation_path)
19
+ configsets = @configsets || @tracked.uniq
20
+ configsets = ["main"] if configsets.empty?
21
+ init = {"configSets" => {"default" => configsets}}.merge(@structure)
22
+ full_structure = { "AWS::CloudFormation::Init" => init }
23
+ full_structure.deep_stringify_keys!
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ class Lono::Configset::Strategy::Dsl
2
+ module Helpers
3
+ end
4
+ end
@@ -0,0 +1,32 @@
1
+ # Core syntax
2
+ class Lono::Configset::Strategy::Dsl
3
+ module Syntax
4
+ extend Memoist
5
+
6
+ %w[package group user resource file command service].each do |meth|
7
+ section = meth.pluralize
8
+ define_method(meth) do |k, props|
9
+ init_empty(@current, section)
10
+ current_structure(@current)[section].deep_merge!(k => props)
11
+ end
12
+ end
13
+
14
+ def configset(current)
15
+ @tracked << current
16
+ previous, @current = @current, current
17
+ yield
18
+ @current = previous
19
+ end
20
+
21
+ private
22
+ def current_structure(configset)
23
+ @structure[configset] ||= {}
24
+ end
25
+ memoize :current_structure
26
+
27
+ def init_empty(configset, section)
28
+ current = current_structure(configset)
29
+ current[section] ||= {}
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,30 @@
1
+ require "json"
2
+
3
+ module Lono::Configset::Strategy
4
+ class Erb < Base
5
+ include Helpers
6
+
7
+ def find_evaluation_path
8
+ paths = %w[configset.yml configset.json].map { |p| "#{@root}/lib/#{p}" }
9
+ paths.find { |p| File.exist?(p) }
10
+ end
11
+
12
+ def load
13
+ content = RenderMePretty.result(@evaluation_path, context: self)
14
+ if File.extname(@evaluation_path) == ".yml"
15
+ load_yaml(content)
16
+ else
17
+ JSON.load(content)
18
+ end
19
+ end
20
+
21
+ def load_yaml(content)
22
+ # Write to file so can use Yamler::Validator
23
+ path = "/tmp/lono/configset.yml"
24
+ FileUtils.mkdir_p(File.dirname(path))
25
+ IO.write(path, content)
26
+ Lono::Yamler::Validator.new(path).validate!
27
+ Lono::Yamler::Loader.new(content).load
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,5 @@
1
- class Lono::Configset::Loader
2
- module Dsl
1
+ class Lono::Configset::Strategy::Erb
2
+ module Helpers
3
3
  def indent(text, indentation_amount)
4
4
  text.split("\n").map do |line|
5
5
  " " * indentation_amount + line
@@ -12,6 +12,7 @@ module Lono
12
12
  blueprint = o[:blueprint] || o[:stack]
13
13
  template = o[:template] || blueprint
14
14
  param = o[:param] || template || blueprint
15
+ stack ||= blueprint # fallback for commands that dont take stack name. IE: lono generate
15
16
  [stack, blueprint, template, param]
16
17
  end
17
18
 
@@ -78,7 +78,7 @@ module Lono::Finder
78
78
  table = Text::Table.new
79
79
  table.head = ["Name", "Path", "Type"]
80
80
 
81
- components = find_all
81
+ components = find_all.sort_by { |jadespec| jadespec.name }
82
82
  components.each do |jadespec|
83
83
  pretty_path = jadespec.root.sub("#{Lono.root}/", "")
84
84
  unless options[:filter_materialized] && jadespec.source_type == "materialized"
@@ -38,17 +38,6 @@ class Lono::Importer
38
38
  path.sub("#{Lono.root}/",'')
39
39
  end
40
40
 
41
- def create_dot_lono(type)
42
- dot_lono = "#{Lono.blueprint_root}/.meta"
43
- FileUtils.mkdir_p(dot_lono)
44
- config = {
45
- "blueprint_name" => @blueprint,
46
- "template_type" => "#{type}",
47
- }
48
- text = YAML.dump(config)
49
- IO.write("#{dot_lono}/config.yml", text)
50
- end
51
-
52
41
  def blueprint_name
53
42
  return @options[:name] if @options[:name]
54
43
  # Else infer name from the original source.
data/lib/lono/jade.rb CHANGED
@@ -7,7 +7,7 @@ module Lono
7
7
  class_attribute :downloaded
8
8
  self.downloaded = []
9
9
 
10
- delegate :template_type, :auto_camelize, :source_type, to: :jadespec
10
+ delegate :source_type, to: :jadespec
11
11
 
12
12
  attr_accessor :dependencies, :from, :depends_ons
13
13
  attr_reader :name, :type, :registry, :jadespec
data/lib/lono/jadespec.rb CHANGED
@@ -25,16 +25,27 @@ module Lono
25
25
  Dir.glob("#{@root}/*.gemspec").first
26
26
  end
27
27
 
28
- def template_type
29
- metadata[:template_type] || "dsl"
28
+ def lono_type
29
+ metadata["lono_type"] || detect_type
30
30
  end
31
31
 
32
+ def detect_type
33
+ configset = Dir.glob("#{@root}/lib/configset.*").size > 0
34
+ configset ? "configset" : "blueprint"
35
+ end
36
+
37
+ def lono_strategy
38
+ return metadata["lono_strategy"] if metadata["lono_strategy"]
39
+ lono_type == "blueprint" ? "dsl" : "erb" # TODO: default to dsl for configset also in next major release
40
+ end
41
+
42
+ # backward-compatiable for now
32
43
  def auto_camelize
33
- metadata[:auto_camelize] || false
44
+ metadata["lono_auto_camelize"] || false
34
45
  end
35
46
 
36
47
  def metadata
37
- gemspec.metadata.deep_symbolize_keys
48
+ gemspec.metadata || {}
38
49
  end
39
50
  memoize :metadata
40
51
  end
@@ -1,5 +1,5 @@
1
1
  module Lono
2
- class ConfigLocation < AbstractBase
2
+ class Layering < AbstractBase
3
3
  extend Memoist
4
4
 
5
5
  def initialize(config, options={}, env=Lono.env, root=Lono.root)
@@ -9,61 +9,45 @@ module Lono
9
9
  @requested = determine_requested
10
10
  end
11
11
 
12
- def lookup
13
- levels = []
14
- levels += direct_levels
15
- # Standard lookup paths
16
- template_level = "#{@root}/configs/#{@blueprint}/#{@config}/#{@env}/#{@template}/#{@requested}"
17
- env_level = "#{@root}/configs/#{@blueprint}/#{@config}/#{@env}/#{@requested}"
18
- config_level = "#{@root}/configs/#{@blueprint}/#{@config}/#{@requested}"
19
- generic_env = "#{@root}/configs/#{@blueprint}/#{@config}/#{@env}"
20
- levels += [template_level, env_level, config_level, generic_env]
21
-
22
- print_levels(levels)
23
-
24
- found = levels.find do |level|
25
- requested_file(level)
26
- end
27
- if found
28
- file = requested_file(found)
29
- using_message(file, @env)
30
- file
31
- end
32
- end
33
-
34
- def direct_levels
35
- [
36
- @requested, # IE: absolute full path
37
- "#{@root}/#{@requested}", # IE : relative path within lono project
38
- ]
12
+ def locations
13
+ paths = always + requested
14
+ layers = paths.map do |path|
15
+ requested_file(path)
16
+ end.compact
17
+ print_layers(layers)
18
+ layers
39
19
  end
40
20
 
41
- def lookup_base
21
+ def always
42
22
  base = "#{@root}/configs/#{@blueprint}/#{@config}/base"
43
- file = requested_file(base)
44
- if file
45
- using_message(file, "base")
46
- file
47
- end
23
+ env = "#{@root}/configs/#{@blueprint}/#{@config}/#{@env}"
24
+ [base, env]
48
25
  end
49
26
 
50
- def print_levels(levels)
51
- return unless ENV["LONO_DEBUG_CONFIG"]
52
- puts "levels #{@config}:"
53
- pp levels
27
+ def requested
28
+ standard_layers + direct_layers
54
29
  end
55
30
 
56
- @@using_message_displayed = {}
57
- def using_message(file, type)
58
- return if @@using_message_displayed[file]
59
-
60
- pretty_file = file.sub("#{Lono.root}/", "")
61
- puts "Using #{@config} for #{type}: #{pretty_file}"
31
+ def standard_layers
32
+ config_level = "#{@root}/configs/#{@blueprint}/#{@config}/#{@requested}"
33
+ env_level = "#{@root}/configs/#{@blueprint}/#{@config}/#{@env}/#{@requested}"
34
+ template_level = "#{@root}/configs/#{@blueprint}/#{@config}/#{@env}/#{@template}/#{@requested}"
35
+ [config_level, env_level, template_level]
36
+ end
62
37
 
63
- @@using_message_displayed[file] = true
38
+ def direct_layers
39
+ if @requested.starts_with?('/')
40
+ [@requested] # IE: absolute full path
41
+ else
42
+ ["#{@root}/#{@requested}"] # IE : relative path within lono project]
43
+ end
64
44
  end
65
45
 
66
- # Some switching logic between variable and param below
46
+ def print_layers(layers)
47
+ return unless ENV["LONO_DEBUG_LAYERING"]
48
+ puts "layers #{@config}:"
49
+ pp layers
50
+ end
67
51
 
68
52
  def determine_requested
69
53
  # param is usually set from the convention. when set from convention stack name takes higher precedence
data/lib/lono/opts.rb CHANGED
@@ -32,6 +32,8 @@ module Lono
32
32
  def template
33
33
  with_cli_scope do
34
34
  option :template, desc: "override convention and specify the template file to use"
35
+ option :param, desc: "override convention and specify the param file to use"
36
+ option :variable, desc: "override convention and specify the variable file to use"
35
37
  end
36
38
  end
37
39
 
@@ -5,27 +5,22 @@ class Lono::Param
5
5
  def generate
6
6
  puts "Generating parameter files for blueprint #{@blueprint.color(:green)}:"
7
7
 
8
- @base_path, @env_path = config_locations
9
-
10
- return {} unless @base_path || @env_path
11
-
12
- # useful option for lono cfn, since some templates dont require params
13
- return {} if @options[:allow_not_exists] && !params_exist?
14
-
15
- if params_exist?
16
- contents = process_erb
17
- data = convert_to_cfn_format(contents)
18
- camel_data = convert_to_cfn_format(contents, :camel)
19
- json = JSON.pretty_generate(camel_data)
20
- write_output(json)
21
- unless @options[:mute]
22
- short_output_path = output_path.sub("#{Lono.root}/","")
23
- puts " #{short_output_path}"
24
- end
25
- else
26
- puts "#{@base_path} or #{@env_path} could not be found? Are you sure it exist?"
27
- exit 1
8
+ contents = []
9
+ layering = Lono::Layering.new("params", @options, Lono.env)
10
+ layering.locations.each do |path|
11
+ contents << render_erb(path)
28
12
  end
13
+ contents = contents.compact.join("\n") # result
14
+
15
+ data = convert_to_cfn_format(contents)
16
+ camel_data = convert_to_cfn_format(contents, :camel)
17
+ json = JSON.pretty_generate(camel_data)
18
+ write_output(json)
19
+ unless @options[:mute]
20
+ short_output_path = output_path.sub("#{Lono.root}/","")
21
+ puts " #{short_output_path}"
22
+ end
23
+
29
24
  data
30
25
  end
31
26
 
@@ -33,66 +28,6 @@ class Lono::Param
33
28
  generate
34
29
  end
35
30
 
36
- def config_locations
37
- @base_path = lookup_config_location("base")
38
- @env_path = lookup_config_location(Lono.env)
39
-
40
- if ENV['LONO_DEBUG_PARAM']
41
- puts "LONO_DEBUG_PARAM enabled"
42
- puts " @base_path #{@base_path.inspect}"
43
- puts " @env_path #{@env_path.inspect}"
44
- end
45
-
46
- [@base_path, @env_path]
47
- end
48
-
49
- def lookup_config_location(env)
50
- location = Lono::ConfigLocation.new("params", @options, env)
51
- env == "base" ? location.lookup_base : location.lookup
52
- end
53
-
54
- def puts_param_message(type)
55
- path = send("#{type}_path")
56
- return unless path
57
- if param_file?(path)
58
- pretty_path = path.sub("#{Lono.root}/",'')
59
- puts "Using param for #{type}: #{pretty_path}".color(:yellow)
60
- end
61
- end
62
-
63
- # Checks both base and source path for existing of the param file.
64
- # Example:
65
- # params/base/mystack.txt - base path
66
- # params/production/mystack.txt - source path
67
- def params_exist?
68
- @base_path && File.exist?(@base_path) ||
69
- @env_path && File.exist?(@env_path)
70
- end
71
-
72
- # Reads both the base source and env source and overlay the two
73
- # Example 1:
74
- # params/base/mystack.txt - base path
75
- # params/production/mystack.txt - env path
76
- #
77
- # the base/mystack.txt gets combined with the prod/mystack.txt
78
- # it produces a final prod/mystack.txt
79
- #
80
- # Example 2:
81
- # params/base/mystack.txt - base path
82
- #
83
- # the base/mystack.txt is used to produced a prod/mystack.txt
84
- #
85
- # Example 3:
86
- # params/production/mystack.txt - env path
87
- #
88
- # the prod/mystack.txt is used to produced a prod/mystack.txt
89
- def process_erb
90
- contents = []
91
- contents << render_erb(@base_path)
92
- contents << render_erb(@env_path)
93
- contents.compact.join("\n") # result
94
- end
95
-
96
31
  def render_erb(path)
97
32
  return unless path
98
33
  if File.exist?(path)
@@ -106,17 +41,6 @@ class Lono::Param
106
41
  @context ||= Lono::Template::Context.new(@options)
107
42
  end
108
43
 
109
- def parse_contents(contents)
110
- lines = contents.split("\n")
111
- # remove comment at the end of the line
112
- lines.map! { |l| l.sub(/#.*/,'').strip }
113
- # filter out commented lines
114
- lines = lines.reject { |l| l =~ /(^|\s)#/i }
115
- # filter out empty lines
116
- lines = lines.reject { |l| l.strip.empty? }
117
- lines
118
- end
119
-
120
44
  def convert_to_cfn_format(contents, casing=:underscore)
121
45
  lines = parse_contents(contents)
122
46
 
@@ -151,6 +75,17 @@ class Lono::Param
151
75
  params
152
76
  end
153
77
 
78
+ def parse_contents(contents)
79
+ lines = contents.split("\n")
80
+ # remove comment at the end of the line
81
+ lines.map! { |l| l.sub(/#.*/,'').strip }
82
+ # filter out commented lines
83
+ lines = lines.reject { |l| l =~ /(^|\s)#/i }
84
+ # filter out empty lines
85
+ lines = lines.reject { |l| l.strip.empty? }
86
+ lines
87
+ end
88
+
154
89
  def remove_surrounding_quotes(s)
155
90
  if s =~ /^"/ && s =~ /"$/
156
91
  s.sub(/^["]/, '').gsub(/["]$/,'') # remove surrounding double quotes
@@ -162,14 +97,7 @@ class Lono::Param
162
97
  end
163
98
 
164
99
  def output_path
165
- output = Lono.config.output_path.sub("#{Lono.root}/","")
166
- path = if @base_path && !@env_path
167
- # Handle case when base config exist but the env config does not
168
- @base_path.sub("configs", output).sub("base", Lono.env)
169
- else
170
- @env_path.sub("configs", output)
171
- end
172
- path.sub(/\.txt$/,'.json')
100
+ "#{Lono.root}/output/#{@blueprint}/params/#{@stack}.json"
173
101
  end
174
102
 
175
103
  def write_output(json)
@@ -141,12 +141,15 @@ class Lono::Sets::Instances
141
141
 
142
142
  def lookup(config_type)
143
143
  config_type = config_type.to_s
144
- base_path = lookup_config_location(config_type, "base")
145
- env_path = lookup_config_location(config_type, Lono.env)
146
- items = load_config(base_path)
147
- items += load_config(env_path)
144
+
145
+ items = []
146
+ layering = Lono::Layering.new(config_type, @options, Lono.env)
147
+ layering.locations.each do |path|
148
+ items += load_config(path)
149
+ end
148
150
  items = items.sort.uniq
149
- if config_type == :accounts
151
+
152
+ if config_type == "accounts"
150
153
  @accounts = items
151
154
  else
152
155
  @regions = items
@@ -166,11 +169,6 @@ class Lono::Sets::Instances
166
169
  items
167
170
  end
168
171
 
169
- def lookup_config_location(config_type, env)
170
- location = Lono::ConfigLocation.new(config_type, @options, env)
171
- env == "base" ? location.lookup_base : location.lookup
172
- end
173
-
174
172
  def validate!
175
173
  invalid = regions.blank? || accounts.blank?
176
174
  if invalid
@@ -11,9 +11,10 @@ class Lono::Template::Context
11
11
  options = ActiveSupport::HashWithIndifferentAccess.new(@options.dup)
12
12
  options[:blueprint] = @blueprint
13
13
  options[:stack] ||= @blueprint
14
- location = Lono::ConfigLocation.new("variables", options, Lono.env)
15
- evaluate_variables_file(location.lookup_base) if location.lookup_base
16
- evaluate_variables_file(location.lookup) if location.lookup # config file
14
+ layering = Lono::Layering.new("variables", options, Lono.env)
15
+ layering.locations.each do |path|
16
+ evaluate_variables_file(path)
17
+ end
17
18
  end
18
19
 
19
20
  # Load the variables defined in config/variables/* to make available in lono scope.
@@ -27,9 +28,9 @@ class Lono::Template::Context
27
28
 
28
29
  # Load custom helper methods from project
29
30
  def load_project_helpers
30
- Dir.glob("#{Lono.config.helpers_path}/**/*_helper.rb").each do |path|
31
- filename = path.sub(%r{.*/},'').sub('.rb','')
32
- module_name = filename.classify
31
+ Dir.glob("#{Lono.config.helpers_path}/**/*.rb").each do |path|
32
+ filename = path.sub("#{Lono.config.helpers_path}/",'').sub('.rb','')
33
+ module_name = filename.camelize
33
34
 
34
35
  # Prepend a period so require works LONO_ROOT is set to a relative path
35
36
  # without a period.
@@ -4,9 +4,9 @@ class Lono::Template
4
4
  class Generator < Lono::AbstractBase
5
5
  def run
6
6
  # Examples:
7
- # Erb.new(b, options.dup).run
8
- # Dsl.new(b, options.dup).run
9
- generator_class = "Lono::Template::Strategy::#{template_type.camelize}"
7
+ # Erb.new(options).run
8
+ # Dsl.new(options).run
9
+ generator_class = "Lono::Template::Strategy::#{lono_strategy.camelize}"
10
10
  generator_class = Object.const_get(generator_class)
11
11
  generator_class.new(@options).run
12
12
  # The generator strategy class writes template to disk. The inject_configsets reads it back from disk.
@@ -14,12 +14,12 @@ class Lono::Template
14
14
  inject_configsets
15
15
  end
16
16
 
17
- def template_type
17
+ def lono_strategy
18
18
  if @options[:source]
19
19
  "source"
20
20
  else
21
- jadespec = Lono::Jadespec.new(Lono.blueprint_root, "unknown") # abusing Jadespec to get template_type
22
- jadespec.template_type
21
+ jadespec = Lono::Jadespec.new(Lono.blueprint_root, "unknown") # abusing Jadespec to get lono_strategy
22
+ jadespec.lono_strategy
23
23
  end
24
24
  end
25
25
 
data/lib/lono/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lono
2
- VERSION = "7.0.5"
2
+ VERSION = "7.1.0"
3
3
  end
@@ -10,11 +10,16 @@ Gem::Specification.new do |spec|
10
10
  spec.summary = "Write a short summary because it's required." # TODO: Change me
11
11
  spec.description = "Write a longer description or delete this line." # TODO: Change me
12
12
  spec.homepage = "<%= ENV['LONO_ORG'] || "https://github.com/USER" %>/<%= blueprint_name %>"
13
- spec.license = "<%= ENV['LONO_LICENSE'] || 'MIT' %>"
13
+ spec.license = "<%= ENV['LONO_LICENSE'] || '' %>"
14
14
 
15
15
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
16
16
  # to allow pushing to a single host or delete this section to allow pushing to any host.
17
17
  if spec.respond_to?(:metadata)
18
+ spec.metadata["lono_type"] = "blueprint"
19
+ <% if @options[:type] != "dsl" %>
20
+ spec.metadata["lono_strategy"] = "erb"
21
+ <% end %>
22
+
18
23
  spec.metadata["allowed_push_host"] = "<%= ENV['LONO_ALLOWED_PUSH_HOST'] || "TODO: Set to 'http://mygemserver.com'"%>"
19
24
 
20
25
  spec.metadata["homepage_uri"] = spec.homepage
@@ -41,7 +46,4 @@ Gem::Specification.new do |spec|
41
46
  spec.add_development_dependency "bundler", "~> 2.0"
42
47
  spec.add_development_dependency "rake", "~> 10.0"
43
48
  spec.add_development_dependency "rspec", "~> 3.0"
44
- <% if @options[:type] != "dsl" %>
45
- spec.metadata = {"template_type" => "erb"}
46
- <% end %>
47
49
  end
@@ -7,11 +7,13 @@ Gem::Specification.new do |spec|
7
7
  spec.summary = "Write a short summary because it's required." # TODO: Change me
8
8
  spec.description = "Write a longer description or delete this line." # TODO: Change me
9
9
  spec.homepage = "<%= ENV['LONO_ORG'] || "https://github.com/USER" %>/<%= configset_name %>"
10
- spec.license = "<%= ENV['LONO_LICENSE'] || 'MIT' %>"
10
+ spec.license = "<%= ENV['LONO_LICENSE'] || '' %>"
11
11
 
12
12
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
13
13
  # to allow pushing to a single host or delete this section to allow pushing to any host.
14
14
  if spec.respond_to?(:metadata)
15
+ spec.metadata["lono_type"] = "configset"
16
+ spec.metadata["lono_strategy"] = "dsl"
15
17
  spec.metadata["allowed_push_host"] = "<%= ENV['LONO_ALLOWED_PUSH_HOST'] || "TODO: Set to 'http://mygemserver.com'"%>"
16
18
 
17
19
  spec.metadata["homepage_uri"] = spec.homepage
@@ -9,3 +9,4 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ Gemfile.lock
@@ -0,0 +1,16 @@
1
+ configset("config1") do
2
+ command("test",
3
+ command: 'echo "$CFNTEST" > test1.txt',
4
+ env: {
5
+ CFNTEST: "I come from config1"
6
+ }
7
+ )
8
+ end
9
+ configset("config2") do
10
+ command("test",
11
+ command: 'echo "$CFNTEST" > test2.txt',
12
+ env: {
13
+ CFNTEST: "I come from config2"
14
+ }
15
+ )
16
+ end
data/lono.gemspec CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |gem|
27
27
  gem.add_dependency "aws-sdk-iam" # lono seed
28
28
  gem.add_dependency "aws-sdk-s3"
29
29
  gem.add_dependency "aws-sdk-ssm"
30
+ gem.add_dependency "bundler", "~> 2"
30
31
  gem.add_dependency "cfn_camelizer"
31
32
  gem.add_dependency "filesize"
32
33
  gem.add_dependency "graph" # lono xgraph command dependency
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lono
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.5
4
+ version: 7.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-29 00:00:00.000000000 Z
11
+ date: 2020-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: bundler
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: cfn_camelizer
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -460,13 +474,11 @@ files:
460
474
  - lib/lono/completer/script.rb
461
475
  - lib/lono/completer/script.sh
462
476
  - lib/lono/completion.rb
463
- - lib/lono/config_location.rb
464
477
  - lib/lono/configset.rb
465
478
  - lib/lono/configset/combiner.rb
466
479
  - lib/lono/configset/evaluate_file.rb
480
+ - lib/lono/configset/generator.rb
467
481
  - lib/lono/configset/list.rb
468
- - lib/lono/configset/loader.rb
469
- - lib/lono/configset/loader/dsl.rb
470
482
  - lib/lono/configset/materializer/final.rb
471
483
  - lib/lono/configset/materializer/gems_builder.rb
472
484
  - lib/lono/configset/materializer/jade.rb
@@ -481,6 +493,12 @@ files:
481
493
  - lib/lono/configset/register/project.rb
482
494
  - lib/lono/configset/registry.rb
483
495
  - lib/lono/configset/resolver.rb
496
+ - lib/lono/configset/strategy/base.rb
497
+ - lib/lono/configset/strategy/dsl.rb
498
+ - lib/lono/configset/strategy/dsl/helpers.rb
499
+ - lib/lono/configset/strategy/dsl/syntax.rb
500
+ - lib/lono/configset/strategy/erb.rb
501
+ - lib/lono/configset/strategy/erb/helpers.rb
484
502
  - lib/lono/conventions.rb
485
503
  - lib/lono/core.rb
486
504
  - lib/lono/core/config.rb
@@ -545,6 +563,7 @@ files:
545
563
  - lib/lono/jade.rb
546
564
  - lib/lono/jade/circular.rb
547
565
  - lib/lono/jadespec.rb
566
+ - lib/lono/layering.rb
548
567
  - lib/lono/md5.rb
549
568
  - lib/lono/new.rb
550
569
  - lib/lono/new/helper.rb
@@ -668,7 +687,7 @@ files:
668
687
  - lib/templates/configset/Gemfile
669
688
  - lib/templates/configset/README.md.tt
670
689
  - lib/templates/configset/Rakefile.tt
671
- - lib/templates/configset/lib/configset.yml
690
+ - lib/templates/configset/lib/configset.rb
672
691
  - lib/templates/skeleton/.gitignore
673
692
  - lib/templates/skeleton/Gemfile
674
693
  - lib/templates/skeleton/README.md
@@ -1,98 +0,0 @@
1
- require "json"
2
-
3
- class Lono::Configset
4
- class Loader
5
- extend Memoist
6
- include Dsl
7
- include EvaluateFile
8
-
9
- def initialize(registry={}, options={})
10
- @registry, @options = registry, options
11
- @name, @resource = registry.name, registry.resource
12
- @blueprint = Lono::Conventions.new(options).blueprint
13
- end
14
-
15
- def metdata_configset
16
- load
17
- end
18
-
19
- def load
20
- path = find_path
21
- copy_instance_variables
22
- content = RenderMePretty.result(path, context: self)
23
- if File.extname(path) == ".yml"
24
- load_yaml(content)
25
- else
26
- JSON.load(content)
27
- end
28
- end
29
- memoize :load
30
-
31
- def load_yaml(content)
32
- # Write to file so can use Yamler::Validator
33
- path = "/tmp/lono/configset.yml"
34
- FileUtils.mkdir_p(File.dirname(path))
35
- IO.write(path, content)
36
- Lono::Yamler::Validator.new(path).validate!
37
- Lono::Yamler::Loader.new(content).load
38
- end
39
-
40
- def find_path
41
- paths = %w[configset.yml configset.json].map { |p| "#{configset_root}/lib/#{p}" }
42
- paths.find { |p| File.exist?(p) }
43
- end
44
-
45
- def configset_root
46
- config = finder_class.find(@name)
47
- unless config
48
- puts "finder_class #{finder_class}"
49
- raise "Unable to find configset #{@name.inspect}"
50
- end
51
- config.root
52
- end
53
-
54
- # Allow overriding in subclasses
55
- def finder_class
56
- Lono::Finder::Configset
57
- end
58
-
59
- def copy_instance_variables
60
- load_blueprint_predefined_variables
61
- load_project_predefined_variables
62
- load_inline_project_variables
63
- end
64
-
65
- def load_blueprint_predefined_variables
66
- path = "#{configset_root}/lib/variables.rb"
67
- evaluate_file(path)
68
- end
69
-
70
- def load_project_predefined_variables
71
- paths = [
72
- "#{Lono.root}/configs/#{@blueprint}/configsets/variables.rb", # global
73
- "#{Lono.root}/configs/#{@blueprint}/configsets/#{@name}/variables.rb", # configset specific
74
- ]
75
- paths.each do |path|
76
- evaluate_file(path)
77
- end
78
- end
79
-
80
- # Copy options from the original configset call as instance variables so its available. So:
81
- #
82
- # configset("ssm", resource: "Instance", some_var: "test")
83
- #
84
- # Stores in the Configset::Registry
85
- #
86
- # register = {name: "ssm", resource: "Instance", some_var: "test"}
87
- #
88
- # That has is passed into Loader.new(register, options)
89
- #
90
- # So these @registry varibles are copied over to instance variables.
91
- #
92
- def load_inline_project_variables
93
- @registry.vars.each do |k,v|
94
- instance_variable_set("@#{k}", v)
95
- end
96
- end
97
- end
98
- end
@@ -1,20 +0,0 @@
1
- ---
2
- AWS::CloudFormation::Init:
3
- configSets:
4
- default:
5
- - config1
6
- - config2
7
- config1:
8
- commands:
9
- test:
10
- command: echo "$CFNTEST" > test.txt
11
- env:
12
- CFNTEST: I come from config1.
13
- cwd: "~"
14
- config2:
15
- commands:
16
- test:
17
- command: echo "$CFNTEST" > test.txt
18
- env:
19
- CFNTEST: I come from config2
20
- cwd: "~"