Class: LeapCli::Config::Object
- Defined in:
- lib/leap_cli/config/object.rb
Overview
This class represents the configuration for a single node, service, or tag. Also, all the nested hashes are also of this type.
It is called ‘object’ because it corresponds to an Object in JSON.
Instance Attribute Summary collapse
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#node ⇒ Object
readonly
Returns the value of attribute node.
Instance Method Summary collapse
-
#[](key) ⇒ Object
FETCHING VALUES.
-
#deep_merge!(object, prefer_self = false) ⇒ Object
A deep (recursive) merge with another Config::Object.
-
#default ⇒ Object
override behavior of #default() from Hash.
-
#dump_json(options = {}) ⇒ Object
export JSON.
-
#dump_yaml ⇒ Object
export YAML.
- #duplicate(env) ⇒ Object
- #environment ⇒ Object
- #environment=(e) ⇒ Object
- #eval_file(filename) ⇒ Object
- #evaluate(context = @node) ⇒ Object
- #get(key) ⇒ Object
-
#get!(key) ⇒ Object
Like a normal Hash#[], except:.
-
#global ⇒ Object
TODO: deprecate node.global().
-
#hkey ⇒ Object
Overrride some default methods in Hash that are likely to be used as attributes.
-
#inherit_from!(object) ⇒ Object
like a reverse deep merge (self takes precedence).
-
#initialize(environment = nil, node = nil) ⇒ Object
constructor
A new instance of Object.
- #key ⇒ Object
- #manager ⇒ Object
-
#method_missing(method, *args, &block) ⇒ Object
make hash addressable like an object (e.g. obj available as obj.name).
-
#pick(*keys) ⇒ Object
Make a copy of ourselves, except only including the specified keys.
- #set_environment(env, node) ⇒ Object
Methods inherited from Hash
Constructor Details
#initialize(environment = nil, node = nil) ⇒ Object
Returns a new instance of Object.
25 26 27 28 29 30 31 |
# File 'lib/leap_cli/config/object.rb', line 25 def initialize(environment=nil, node=nil) raise ArgumentError unless environment.nil? || environment.is_a?(Config::Environment) @env = environment # an object that is a node as @node equal to self, otherwise all the # child objects point back to the top level node. @node = node || self end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
Instance Attribute Details
#env ⇒ Object (readonly)
Returns the value of attribute env.
22 23 24 |
# File 'lib/leap_cli/config/object.rb', line 22 def env @env end |
#node ⇒ Object (readonly)
Returns the value of attribute node.
23 24 25 |
# File 'lib/leap_cli/config/object.rb', line 23 def node @node end |
Instance Method Details
#[](key) ⇒ Object
FETCHING VALUES
101 102 103 |
# File 'lib/leap_cli/config/object.rb', line 101 def [](key) get(key) end |
#deep_merge!(object, prefer_self = false) ⇒ Object
A deep (recursive) merge with another Config::Object.
If prefer_self is set to true, the value from self will be picked when there is a conflict that cannot be merged.
Merging rules:
-
If a value is a hash, we recursively merge it.
-
If the value is simple, like a string, the new one overwrites the value.
-
If the value is an array:
-
If both old and new values are arrays, the new one replaces the old.
-
If one of the values is simple but the other is an array, the simple is added to the array.
-
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/leap_cli/config/object.rb', line 174 def deep_merge!(object, prefer_self=false) object.each do |key,new_value| 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) elsif self.has_key?('!'+key) mode = :replace 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" new_value = false if new_value == "false" old_value = true if old_value == "true" old_value = false if old_value == "false" # force replace? if mode == :replace && prefer_self value = old_value # merge hashes elsif old_value.is_a?(Hash) || new_value.is_a?(Hash) value = Config::Object.new(@env, @node) old_value.is_a?(Hash) ? value.deep_merge!(old_value) : (value[key] = old_value if !old_value.nil?) new_value.is_a?(Hash) ? value.deep_merge!(new_value, prefer_self) : (value[key] = new_value if !new_value.nil?) # merge nil elsif new_value.nil? value = old_value elsif old_value.nil? value = new_value # merge arrays when one value is not an array elsif old_value.is_a?(Array) && !new_value.is_a?(Array) (value = (old_value.dup << new_value).compact.uniq).delete('REQUIRED') 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".' % [ old_value.inspect, old_value.class, new_value.inspect, new_value.class, key, self.class ] # merge simple strings & numbers else if prefer_self value = old_value else value = new_value end end # save value self[key] = value end self end |
#default ⇒ Object
override behavior of #default() from Hash
126 127 128 |
# File 'lib/leap_cli/config/object.rb', line 126 def default get!('default') end |
#dump_json(options = {}) ⇒ Object
export JSON
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/leap_cli/config/object.rb', line 72 def dump_json(={}) evaluate(@node) if [:format] == :compact return self.to_json else excluded = {} if [:exclude] [:exclude].each do |key| excluded[key] = self[key] self.delete(key) end end json_str = JSON.sorted_generate(self) if excluded.any? self.merge!(excluded) end return json_str end end |
#dump_yaml ⇒ Object
export YAML
We use pure ruby yaml exporter ya2yaml instead of SYCK or PSYCH because it allows us greater compatibility regardless of installed ruby version and greater control over how the yaml is exported (sorted keys, in particular).
64 65 66 67 |
# File 'lib/leap_cli/config/object.rb', line 64 def dump_yaml evaluate(@node) sorted_ya2yaml(:syck_compatible => true) end |
#duplicate(env) ⇒ Object
52 53 54 55 |
# File 'lib/leap_cli/config/object.rb', line 52 def duplicate(env) new_object = self.deep_dup new_object.set_environment(env, new_object) end |
#environment ⇒ Object
48 49 50 |
# File 'lib/leap_cli/config/object.rb', line 48 def environment self['environment'] end |
#environment=(e) ⇒ Object
44 45 46 |
# File 'lib/leap_cli/config/object.rb', line 44 def environment=(e) self.store('environment', e) end |
#eval_file(filename) ⇒ Object
289 290 291 |
# File 'lib/leap_cli/config/object.rb', line 289 def eval_file(filename) evaluate_ruby(filename, File.read(filename)) end |
#evaluate(context = @node) ⇒ Object
92 93 94 95 |
# File 'lib/leap_cli/config/object.rb', line 92 def evaluate(context=@node) evaluate_everything(context) late_evaluate_everything(context) end |
#get(key) ⇒ Object
117 118 119 120 121 122 123 |
# File 'lib/leap_cli/config/object.rb', line 117 def get(key) begin get!(key) rescue NoMethodError nil end end |
#get!(key) ⇒ Object
Like a normal Hash#[], except:
(1) lazily eval dynamic values when we encounter them. (i.e. strings that start with “= ”)
(2) support for nested references in a single string (e.g. [‘a.b’] is the same as [‘a’])
the dot path is always absolute, starting at the top-most object.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/leap_cli/config/object.rb', line 138 def get!(key) key = key.to_s if self.has_key?(key) fetch_value(key) elsif key =~ /\./ # for keys with with '.' in them, we start from the root object (@node). keys = key.split('.') value = self.get!(keys.first) if value.is_a? Config::Object value.get!(keys[1..-1].join('.')) else value end else raise NoMethodError.new(key, "No method '#{key}' for #{self.class}") end end |
#global ⇒ Object
TODO: deprecate node.global()
40 41 42 |
# File 'lib/leap_cli/config/object.rb', line 40 def global @env end |
#hkey ⇒ Object
Overrride some default methods in Hash that are likely to be used as attributes.
107 |
# File 'lib/leap_cli/config/object.rb', line 107 alias_method :hkey, :key |
#inherit_from!(object) ⇒ Object
like a reverse deep merge (self takes precedence)
270 271 272 |
# File 'lib/leap_cli/config/object.rb', line 270 def inherit_from!(object) self.deep_merge!(object, true) end |
#key ⇒ Object
108 |
# File 'lib/leap_cli/config/object.rb', line 108 def key; get('key'); end |
#manager ⇒ Object
33 34 35 |
# File 'lib/leap_cli/config/object.rb', line 33 def manager @env.manager end |
#pick(*keys) ⇒ Object
Make a copy of ourselves, except only including the specified keys.
Also, the result is flattened to a single hash, so a key of ‘a.b’ becomes ‘a_b’
279 280 281 282 283 284 285 286 287 |
# File 'lib/leap_cli/config/object.rb', line 279 def pick(*keys) keys.map(&:to_s).inject(self.class.new(@manager)) do |hsh, key| value = self.get(key) if !value.nil? hsh[key.gsub('.','_')] = value end hsh end end |
#set_environment(env, node) ⇒ Object
256 257 258 259 260 261 262 263 264 |
# File 'lib/leap_cli/config/object.rb', line 256 def set_environment(env, node) @env = env @node = node self.each do |key, value| if value.is_a?(Config::Object) value.set_environment(env, node) end end end |