From 04b56f69bcd80e2440442ea027bf7a3cc69d8155 Mon Sep 17 00:00:00 2001 From: "Marc A. Paradise" Date: Thu, 14 Nov 2019 12:16:30 -0500 Subject: Do not crash when loading undefined context from hash When loading `from_hash` and with `strict_mode false`, a config context that is not defined will cause mixlib-config to crash. This is because we used `internal_get` without checking to see if the result was nil. nil occurs when the scenario above is met. Now, we will define the context when this happens, and continue to populate that context from the hash. Signed-off-by: Marc A. Paradise --- lib/mixlib/config.rb | 5 +++- spec/mixlib/config_spec.rb | 57 ++++++++++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/lib/mixlib/config.rb b/lib/mixlib/config.rb index 9937182..00385da 100644 --- a/lib/mixlib/config.rb +++ b/lib/mixlib/config.rb @@ -569,7 +569,10 @@ module Mixlib def apply_nested_hash(hash) hash.each do |k, v| if v.is_a? Hash - internal_get(k.to_sym).apply_nested_hash(v) + # If loading from hash, and we reference a context that doesn't exist + # and warning/strict is off, we need to create the config context that we expected to be here. + context = internal_get(k.to_sym) || config_context(k.to_sym) + context.apply_nested_hash(v) else internal_set(k.to_sym, v) end diff --git a/spec/mixlib/config_spec.rb b/spec/mixlib/config_spec.rb index de4147b..1155e75 100644 --- a/spec/mixlib/config_spec.rb +++ b/spec/mixlib/config_spec.rb @@ -1274,28 +1274,45 @@ describe Mixlib::Config do end describe ".from_hash" do - let(:hash) do - { - "alpha" => "beta", - gamma: "delta", - "foo" => %w{ bar baz matazz}, - "bar" => { "baz" => { "fizz" => "buzz" } }, - "windows_path" => 'C:\Windows Has Awful\Paths', - } - end - - it "configures the config object from a hash" do - ConfigIt.config_context :bar do - config_context :baz do - default :fizz, "quux" + context "when contexts in the hash are defined" do + let(:hash) do + { + "alpha" => "beta", + gamma: "delta", + "foo" => %w{ bar baz matazz}, + "bar" => { "baz" => { "fizz" => "buzz" } }, + "windows_path" => 'C:\Windows Has Awful\Paths', + } + end + 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.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 + context "when contexts in the hash are undefined and strict disabled" do + before do + ConfigIt.strict_mode = true + end + let(:hash) do + { + "brrr" => { "baz" => { "fizz" => "buzz" } }, + "windows_path" => 'C:\Windows Has Awful\Paths', + } + end + it "configures the config object, creating contexts as needed" do + ConfigIt.from_hash(hash) + expect(ConfigIt[:brrr][:baz][:fizz]).to eql("buzz") + expect(ConfigIt.windows_path).to eql('C:\Windows Has Awful\Paths') end - 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 -- cgit v1.2.1