From c43316fd69daa98e8f1b713622428b0f75da5f1f Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Wed, 11 Jul 2018 12:23:43 -0700 Subject: [PATCH 1/3] Avoid converting to text representation when parsing JSON/TOML/etc Directly apply the config as we descend recursively through the Hash using internal_set/internal_get. Signed-off-by: Lamont Granquist --- lib/mixlib/config.rb | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/mixlib/config.rb b/lib/mixlib/config.rb index 1c8daa4..3ef06e8 100644 --- a/lib/mixlib/config.rb +++ b/lib/mixlib/config.rb @@ -70,7 +70,7 @@ def from_file(filename) # filename:: A filename to read from def from_yaml(filename) require "yaml" - from_hash(YAML.load(IO.read(filename)), filename) + from_hash(YAML.load(IO.read(filename))) end # Parses valid JSON structure into Ruby @@ -79,7 +79,7 @@ def from_yaml(filename) # filename:: A filename to read from def from_json(filename) require "json" - from_hash(JSON.parse(IO.read(filename)), filename) + from_hash(JSON.parse(IO.read(filename))) end def from_toml(filename) @@ -91,20 +91,8 @@ def from_toml(filename) # # === Parameters # hash:: A Hash containing configuration - def from_hash(hash, filename = "in_memory") - ruby_translation = [] - - to_dotted_hash(hash).each do |k, v| - if v.is_a? Array - ruby_translation << "#{k} #{v}" - elsif v.is_a? String - ruby_translation << "#{k} \"#{v}\"" - else - ruby_translation << "#{k} #{v}" - end - end - - instance_eval(ruby_translation.join("\n"), filename, 1) + def from_hash(hash) + apply_nested_hash(hash) end # Pass Mixlib::Config.configure() a block, and it will yield itself @@ -590,6 +578,23 @@ def to_dotted_hash(hash, recursive_key = "") end end + # Given a (nested) Hash, apply it to the config object and any contexts. + # + # This is preferable to converting it to the string representation with + # the #to_dotted_hash method above. + # + # === Parameters + # hash:: The hash to apply to the config oject + def apply_nested_hash(hash) + hash.each do |k, v| + if v.is_a? Hash + internal_get(k.to_sym).apply_nested_hash(v) + else + internal_set(k.to_sym, v) + end + end + end + # Internal dispatch setter for config values. # # === Parameters From a65cb52db5985e602a46f5375295761b6f04bb68 Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Wed, 11 Jul 2018 12:57:34 -0700 Subject: [PATCH 2/3] test+fix config contexts Signed-off-by: Lamont Granquist --- lib/mixlib/config.rb | 36 +++++++++++++++++++----------------- spec/mixlib/config_spec.rb | 9 ++++++++- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/lib/mixlib/config.rb b/lib/mixlib/config.rb index 3ef06e8..aa56cea 100644 --- a/lib/mixlib/config.rb +++ b/lib/mixlib/config.rb @@ -555,6 +555,25 @@ def method_missing(method_symbol, *args) internal_get_or_set(method_symbol, *args) end + protected + + # Given a (nested) Hash, apply it to the config object and any contexts. + # + # This is preferable to converting it to the string representation with + # the #to_dotted_hash method above. + # + # === Parameters + # hash:: The hash to apply to the config oject + def apply_nested_hash(hash) + hash.each do |k, v| + if v.is_a? Hash + internal_get(k.to_sym).apply_nested_hash(v) + else + internal_set(k.to_sym, v) + end + end + end + private # Given a (nested) Hash, turn it into a single top-level hash using dots as @@ -578,23 +597,6 @@ def to_dotted_hash(hash, recursive_key = "") end end - # Given a (nested) Hash, apply it to the config object and any contexts. - # - # This is preferable to converting it to the string representation with - # the #to_dotted_hash method above. - # - # === Parameters - # hash:: The hash to apply to the config oject - def apply_nested_hash(hash) - hash.each do |k, v| - if v.is_a? Hash - internal_get(k.to_sym).apply_nested_hash(v) - else - internal_set(k.to_sym, v) - end - end - end - # Internal dispatch setter for config values. # # === Parameters diff --git a/spec/mixlib/config_spec.rb b/spec/mixlib/config_spec.rb index 1786789..ca86b01 100644 --- a/spec/mixlib/config_spec.rb +++ b/spec/mixlib/config_spec.rb @@ -1278,13 +1278,20 @@ class StrictClass3 { "alpha" => "beta", "foo" => %w{ bar baz matazz}, + "bar" => { "baz" => { "fizz" => "buzz" } }, } end - it "translates the Hash into method-style" do + it "configures the config object from a hash" do + ConfigIt.config_context :bar do + config_context :baz do + default :fizz, "quux" + end + end ConfigIt.from_hash(hash) expect(ConfigIt.foo).to eql(%w{ bar baz matazz }) expect(ConfigIt.alpha).to eql("beta") + expect(ConfigIt[:bar][:baz][:fizz]).to eql("buzz") end end end From 1e76fdf03d4ba680cef4b9e35449a2b6e5e55c7b Mon Sep 17 00:00:00 2001 From: Lamont Granquist Date: Wed, 11 Jul 2018 13:54:51 -0700 Subject: [PATCH 3/3] add some more tests Signed-off-by: Lamont Granquist --- spec/mixlib/config_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/mixlib/config_spec.rb b/spec/mixlib/config_spec.rb index ca86b01..a08e3cc 100644 --- a/spec/mixlib/config_spec.rb +++ b/spec/mixlib/config_spec.rb @@ -1277,8 +1277,10 @@ class StrictClass3 let(:hash) do { "alpha" => "beta", + gamma: "delta", "foo" => %w{ bar baz matazz}, "bar" => { "baz" => { "fizz" => "buzz" } }, + "windows_path" => 'C:\Windows Has Awful\Paths', } end @@ -1291,7 +1293,9 @@ class StrictClass3 ConfigIt.from_hash(hash) expect(ConfigIt.foo).to eql(%w{ bar baz matazz }) expect(ConfigIt.alpha).to eql("beta") + expect(ConfigIt.gamma).to eql("delta") expect(ConfigIt[:bar][:baz][:fizz]).to eql("buzz") + expect(ConfigIt.windows_path).to eql('C:\Windows Has Awful\Paths') end end end