mirror of
https://github.com/inspec/inspec
synced 2024-11-11 07:34:15 +00:00
Support symbol keys in ObjectTraverser (#2221)
As detected in #2036, it is not possible to extract values from a YAML file if the key is a symbol. This change refactors ObjectTraverser to support symbol keys before attempting to stringify them. Signed-off-by: Adam Leff <adam@leff.co>
This commit is contained in:
parent
359fd48af0
commit
9d8c53cf31
4 changed files with 59 additions and 12 deletions
|
@ -3,22 +3,47 @@
|
||||||
# author: Christoph Hartmann
|
# author: Christoph Hartmann
|
||||||
module ObjectTraverser
|
module ObjectTraverser
|
||||||
def extract_value(keys, value)
|
def extract_value(keys, value)
|
||||||
key = keys.shift
|
return nil if value.nil?
|
||||||
return nil if key.nil? || value.nil?
|
|
||||||
|
|
||||||
if value.is_a?(Array)
|
key = keys.shift
|
||||||
value = if key.is_a?(Fixnum)
|
return nil if key.nil?
|
||||||
value[key]
|
|
||||||
elsif value.respond_to?(key.to_sym)
|
# if the current value is not a Hash or Array, it is undefined
|
||||||
value.send(key.to_sym)
|
# behavior so value will be assigned nil by default.
|
||||||
end
|
value = if value.is_a?(Array)
|
||||||
else
|
extract_from_array(key, value)
|
||||||
value = value[key.to_s].nil? ? nil : value[key.to_s]
|
elsif value.is_a?(Hash)
|
||||||
end
|
extract_from_hash(key, value)
|
||||||
|
end
|
||||||
|
|
||||||
# if there are no more keys, just return the value
|
# if there are no more keys, just return the value
|
||||||
return value if keys.first.nil?
|
return value if keys.first.nil?
|
||||||
# if there are more keys, extract more
|
# if there are more keys, extract more
|
||||||
extract_value(keys.clone, value)
|
extract_value(keys.clone, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# If the values to return from is an Array, allow returning by index.
|
||||||
|
# Otherwise, support methods on the Array itself.
|
||||||
|
def extract_from_array(key, value)
|
||||||
|
if key.is_a?(Fixnum)
|
||||||
|
value[key]
|
||||||
|
elsif value.respond_to?(key.to_sym)
|
||||||
|
value.send(key.to_sym)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# for Hashes, try to return the value by the key.
|
||||||
|
# We first try to find by the raw key before we stringify
|
||||||
|
# if the keys themselves are symbols, for example.
|
||||||
|
#
|
||||||
|
# This will return nil default if we can't find the key.
|
||||||
|
def extract_from_hash(key, value)
|
||||||
|
if value.key?(key)
|
||||||
|
value[key]
|
||||||
|
elsif value.key?(key.to_s)
|
||||||
|
value[key.to_s]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,3 +5,6 @@ driver:
|
||||||
platforms:
|
platforms:
|
||||||
- linux
|
- linux
|
||||||
- mac
|
- mac
|
||||||
|
:symbol_key: 123
|
||||||
|
:symbol_key_deep:
|
||||||
|
foo: bar
|
||||||
|
|
|
@ -30,5 +30,13 @@ describe 'Inspec::Resources::YAML' do
|
||||||
it 'doesnt resolve symbol-notation names' do
|
it 'doesnt resolve symbol-notation names' do
|
||||||
_(resource.send(:'driver.customize.memory')).must_be_nil
|
_(resource.send(:'driver.customize.memory')).must_be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'supports fetching by symbol keys' do
|
||||||
|
_(resource.send(:symbol_key)).must_equal 123
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'support fetching by symbol keys in array syntax for rspec-its' do
|
||||||
|
_(resource.send(:[], :symbol_key_deep, 'foo')).must_equal 'bar'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,7 +25,12 @@ describe ObjectTraverser do
|
||||||
123,
|
123,
|
||||||
456,
|
456,
|
||||||
{ 'array1hashkey1' => 1, 'array1hashkey2' => 2 },
|
{ 'array1hashkey1' => 1, 'array1hashkey2' => 2 },
|
||||||
]
|
],
|
||||||
|
:symbol_key_1 => 123,
|
||||||
|
:symbol_key_2 => {
|
||||||
|
:symbol_under_symbol => 456,
|
||||||
|
'string_under_symbol' => 789
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -77,4 +82,10 @@ describe ObjectTraverser do
|
||||||
subject.extract_value(['array2', 'last', 'array1hashkey1'], sample_data).must_equal(1)
|
subject.extract_value(['array2', 'last', 'array1hashkey1'], sample_data).must_equal(1)
|
||||||
subject.extract_value(['array2', 'last', 'array1hashkey2'], sample_data).must_equal(2)
|
subject.extract_value(['array2', 'last', 'array1hashkey2'], sample_data).must_equal(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'supports returning values with symbol keys' do
|
||||||
|
subject.extract_value([:symbol_key_1], sample_data).must_equal(123)
|
||||||
|
subject.extract_value([:symbol_key_2, :symbol_under_symbol], sample_data).must_equal(456)
|
||||||
|
subject.extract_value([:symbol_key_2, 'string_under_symbol'], sample_data).must_equal(789)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue