diff options
Diffstat (limited to 'lib/leap_cli/config/object.rb')
-rw-r--r-- | lib/leap_cli/config/object.rb | 113 |
1 files changed, 69 insertions, 44 deletions
diff --git a/lib/leap_cli/config/object.rb b/lib/leap_cli/config/object.rb index 2392d1c..a0d402b 100644 --- a/lib/leap_cli/config/object.rb +++ b/lib/leap_cli/config/object.rb @@ -8,8 +8,6 @@ if $ruby_version < [1,9] end require 'ya2yaml' # pure ruby yaml -require 'leap_cli/config/macros' - module LeapCli module Config # @@ -20,8 +18,6 @@ module LeapCli # class Object < Hash - include Config::Macros - attr_reader :node attr_reader :manager alias :global :manager @@ -44,7 +40,7 @@ module LeapCli # def dump_yaml evaluate(@node) - ya2yaml(:syck_compatible => true) + sorted_ya2yaml(:syck_compatible => true) end # @@ -68,6 +64,11 @@ module LeapCli get(key) end + # Overrride some default methods in Hash that are likely to + # be used as attributes. + alias_method :hkey, :key + def key; get('key'); end + # # make hash addressable like an object (e.g. obj['name'] available as obj.name) # @@ -134,7 +135,18 @@ module LeapCli # def deep_merge!(object, prefer_self=false) object.each do |key,new_value| - old_value = self.fetch key, nil + if self.has_key?('+'+key) + mode = :add + old_value = self.fetch '+'+key, nil + self.delete('+'+key) + elsif self.has_key?('-'+key) + mode = :subtract + old_value = self.fetch '-'+key, nil + self.delete('-'+key) + else + mode = :normal + old_value = self.fetch key, nil + end # clean up boolean new_value = true if new_value == "true" @@ -160,6 +172,18 @@ module LeapCli elsif new_value.is_a?(Array) && !old_value.is_a?(Array) (value = (new_value.dup << old_value).compact.uniq).delete('REQUIRED') + # merge two arrays + elsif old_value.is_a?(Array) && new_value.is_a?(Array) + if mode == :add + value = (old_value + new_value).sort.uniq + elsif mode == :subtract + value = new_value - old_value + elsif prefer_self + value = old_value + else + value = new_value + end + # catch errors elsif type_mismatch?(old_value, new_value) raise 'Type mismatch. Cannot merge %s (%s) with %s (%s). Key is "%s", name is "%s".' % [ @@ -168,7 +192,7 @@ module LeapCli key, self.class ] - # merge strings, numbers, and sometimes arrays + # merge simple strings & numbers else if prefer_self value = old_value @@ -206,6 +230,10 @@ module LeapCli end end + def eval_file(filename) + evaluate_ruby(filename, File.read(filename)) + end + protected # @@ -246,45 +274,42 @@ module LeapCli # (`key` is just passed for debugging purposes) # def evaluate_ruby(key, value) - result = nil - if LeapCli.log_level >= 2 - result = self.instance_eval(value) - else - begin - result = self.instance_eval(value) - rescue SystemStackError => exc - Util::log 0, :error, "while evaluating node '#{self.name}'" - Util::log 0, "offending key: #{key}", :indent => 1 - Util::log 0, "offending string: #{value}", :indent => 1 - Util::log 0, "STACK OVERFLOW, BAILING OUT. There must be an eval loop of death (variables with circular dependencies).", :indent => 1 - raise SystemExit.new(1) - rescue FileMissing => exc - Util::bail! do - if exc.options[:missing] - Util::log :missing, exc.options[:missing].gsub('$node', self.name).gsub('$file', exc.path) - else - Util::log :error, "while evaluating node '#{self.name}'" - Util::log "offending key: #{key}", :indent => 1 - Util::log "offending string: #{value}", :indent => 1 - Util::log "error message: no file '#{exc}'", :indent => 1 - end - end - rescue AssertionFailed => exc - Util.bail! do - Util::log :failed, "assertion while evaluating node '#{self.name}'" - Util::log 'assertion: %s' % exc.assertion, :indent => 1 - Util::log "offending key: #{key}", :indent => 1 - end - rescue SyntaxError, StandardError => exc - Util::bail! do - Util::log :error, "while evaluating node '#{self.name}'" - Util::log "offending key: #{key}", :indent => 1 - Util::log "offending string: #{value}", :indent => 1 - Util::log "error message: #{exc.inspect}", :indent => 1 - end + self.instance_eval(value, key, 1) + rescue ConfigError => exc + raise exc # pass through + rescue SystemStackError => exc + Util::log 0, :error, "while evaluating node '#{self.name}'" + Util::log 0, "offending key: #{key}", :indent => 1 + Util::log 0, "offending string: #{value}", :indent => 1 + Util::log 0, "STACK OVERFLOW, BAILING OUT. There must be an eval loop of death (variables with circular dependencies).", :indent => 1 + raise SystemExit.new(1) + rescue FileMissing => exc + Util::bail! do + if exc.options[:missing] + Util::log :missing, exc.options[:missing].gsub('$node', self.name).gsub('$file', exc.path) + else + Util::log :error, "while evaluating node '#{self.name}'" + Util::log "offending key: #{key}", :indent => 1 + Util::log "offending string: #{value}", :indent => 1 + Util::log "error message: no file '#{exc}'", :indent => 1 end + raise exc if DEBUG + end + rescue AssertionFailed => exc + Util.bail! do + Util::log :failed, "assertion while evaluating node '#{self.name}'" + Util::log 'assertion: %s' % exc.assertion, :indent => 1 + Util::log "offending key: #{key}", :indent => 1 + raise exc if DEBUG + end + rescue SyntaxError, StandardError => exc + Util::bail! do + Util::log :error, "while evaluating node '#{self.name}'" + Util::log "offending key: #{key}", :indent => 1 + Util::log "offending string: #{value}", :indent => 1 + Util::log "error message: #{exc.inspect}", :indent => 1 + raise exc if DEBUG end - return result end private |