Reputation: 531
I wrote a small Chef library that looks like this:
module Test
module Search
extend self
def single_node(type, value)
result = Chef::Search::Query.new.search(:node, "#{type}:#{value}",
filter_result: {
'name' => ['name']
}).map { |n| n['name'] }.first
return result
end
end
end
When running test code against it I get the following error:
TypeError
---------
no implicit conversion of String into Integer
1: module Test
2: module Search
3: extend self
4: def single_node(type, value)
5: result = Chef::Search::Query.new.search(:node, "#{type}:#{value}",
6: filter_result: {
7: 'name' => ['name']
8>> }).map { |n| n['name'] }.first
9: return result
10: end
13: end
14:
After some playing around I found that the search contained this information:
[[{"name"=>"influxdb.example.org"}], 0, 1].
This seems odd as the search options used return something different when searching from within the Chef DSL.
Upvotes: 2
Views: 1785
Reputation: 15784
When executing the search in a recipe you're calling the search method in recipe DSL, which already iterate over the results before sending them back.
When you call Chef::Sarch::Query.new.search
you're calling the underlying method out of the dsl helper and have to iterate over the results yourself if you don't pass a block to the method to work on the results.
You end up here which returns an array containing the query result array, along with the start and size of results (for pagination on UI).
So the final answer as already been given by @Oleander, call first
before map
, to call map
in the result part of the return (first array entry) ignoring the pagination variables.
Or to get the same behavior as in the recipe DSL use Chef::DSL::DataQuery like this:
require 'chef/dsl/data_query'
module Test
module Search
extend self
include Chef::DSL::DataQuery
def single_node(type, value)
result = search(:node, "#{type}:#{value}",
filter_result: {
'name' => ['name']
}).map { |n| n['name'] }.first
return result
end
end
end
On the same idea to shorten your code:
require 'chef/dsl/data_query'
module Test
module Search
extend self
include Chef::DSL::DataQuery
def single_node(type, value)
return search(:node, "#{type}:#{value}",
filter_result: {
'name' => ['name']
}).first['name']
end
end
end
Which return the first result too and get it's name, should be a little quicker as it does not have to 'subset' all entries but only the first one.
Upvotes: 4
Reputation: 18157
If what you posted is your return value, then just run first
on it and you're done.
result = Chef::Search::Query.new.search(:node, "#{type}:#{value}", filter_result: {
'name' => ['name']
}).first.map { |n| n['name'] }.first
Upvotes: 2