aboutsummaryrefslogtreecommitdiff
path: root/lib/leap_cli/config/object.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/leap_cli/config/object.rb')
-rw-r--r--lib/leap_cli/config/object.rb113
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