lono 7.0.5 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: "~"