/usr/lib/ruby/vendor_ruby/chef_zero/endpoints/search_endpoint.rb is in chef-zero 4.5.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | require 'ffi_yajl'
require 'chef_zero/endpoints/rest_object_endpoint'
require 'chef_zero/chef_data/data_normalizer'
require 'chef_zero/rest_error_response'
require 'chef_zero/solr/solr_parser'
require 'chef_zero/solr/solr_doc'
module ChefZero
module Endpoints
# /search/INDEX
class SearchEndpoint < RestBase
def get(request)
orgname = request.rest_path[1]
results = search(request, orgname)
results['rows'] = results['rows'].map { |name,uri,value,search_value| value }
json_response(200, results)
end
def post(request)
orgname = request.rest_path[1]
full_results = search(request, orgname)
keys = FFI_Yajl::Parser.parse(request.body, :create_additions => false)
partial_results = full_results['rows'].map do |name, uri, doc, search_value|
data = {}
keys.each_pair do |key, path|
if path.size > 0
value = search_value
path.each do |path_part|
value = value[path_part] if !value.nil?
end
data[key] = value
else
data[key] = nil
end
end
{
'url' => uri,
'data' => data
}
end
json_response(200, {
'rows' => partial_results,
'start' => full_results['start'],
'total' => full_results['total']
})
end
private
def search_container(request, index, orgname)
relative_parts, normalize_proc = case index
when 'client'
[ ['clients'], Proc.new { |client, name| ChefData::DataNormalizer.normalize_client(client, name, orgname) } ]
when 'node'
[ ['nodes'], Proc.new { |node, name| ChefData::DataNormalizer.normalize_node(node, name) } ]
when 'environment'
[ ['environments'], Proc.new { |environment, name| ChefData::DataNormalizer.normalize_environment(environment, name) } ]
when 'role'
[ ['roles'], Proc.new { |role, name| ChefData::DataNormalizer.normalize_role(role, name) } ]
else
[ ['data', index], Proc.new { |data_bag_item, id| ChefData::DataNormalizer.normalize_data_bag_item(data_bag_item, index, id, 'DELETE') } ]
end
[
request.rest_path[0..1] + relative_parts,
normalize_proc
]
end
def expand_for_indexing(value, index, id)
if index == 'node'
result = {}
deep_merge!(value['default'] || {}, result)
deep_merge!(value['normal'] || {}, result)
deep_merge!(value['override'] || {}, result)
deep_merge!(value['automatic'] || {}, result)
result['recipe'] = []
result['role'] = []
if value['run_list']
value['run_list'].each do |run_list_entry|
if run_list_entry =~ /^(recipe|role)\[(.*)\]/
result[$1] << $2
end
end
end
value.each_pair do |key, value|
result[key] = value unless %w(default normal override automatic).include?(key)
end
result
elsif !%w(client environment role).include?(index)
ChefData::DataNormalizer.normalize_data_bag_item(value, index, id, 'GET')
else
value
end
end
def search(request, orgname = nil)
# Extract parameters
index = request.rest_path[3]
query_string = request.query_params['q'] || '*:*'
solr_query = ChefZero::Solr::SolrParser.new(query_string).parse
sort_string = request.query_params['sort']
start = request.query_params['start']
start = start.to_i if start
rows = request.query_params['rows']
rows = rows.to_i if rows
# Get the search container
container, expander = search_container(request, index, orgname)
# Search!
result = []
list_data(request, container).each do |name|
value = get_data(request, container + [name])
expanded = expander.call(FFI_Yajl::Parser.parse(value, :create_additions => false), name)
result << [ name, build_uri(request.base_uri, container + [name]), expanded, expand_for_indexing(expanded, index, name) ]
end
result = result.select do |name, uri, value, search_value|
solr_query.matches_doc?(ChefZero::Solr::SolrDoc.new(search_value, name))
end
total = result.size
# Sort
if sort_string
sort_key, sort_order = sort_string.split(/\s+/, 2)
result = result.sort_by { |name,uri,value,search_value| ChefZero::Solr::SolrDoc.new(search_value, name)[sort_key] }
result = result.reverse if sort_order == "DESC"
end
# Paginate
if start
result = result[start..start+(rows||-1)]
end
{
'rows' => result,
'start' => start || 0,
'total' => total
}
end
private
# Deep Merge core documentation.
# deep_merge! method permits merging of arbitrary child elements. The two top level
# elements must be hashes. These hashes can contain unlimited (to stack limit) levels
# of child elements. These child elements to not have to be of the same types.
# Where child elements are of the same type, deep_merge will attempt to merge them together.
# Where child elements are not of the same type, deep_merge will skip or optionally overwrite
# the destination element with the contents of the source element at that level.
# So if you have two hashes like this:
# source = {:x => [1,2,3], :y => 2}
# dest = {:x => [4,5,'6'], :y => [7,8,9]}
# dest.deep_merge!(source)
# Results: {:x => [1,2,3,4,5,'6'], :y => 2}
# By default, "deep_merge!" will overwrite any unmergeables and merge everything else.
# To avoid this, use "deep_merge" (no bang/exclamation mark)
def deep_merge!(source, dest)
# if dest doesn't exist, then simply copy source to it
if dest.nil?
dest = source; return dest
end
case source
when nil
dest
when Hash
source.each do |src_key, src_value|
if dest.kind_of?(Hash)
if dest[src_key]
dest[src_key] = deep_merge!(src_value, dest[src_key])
else # dest[src_key] doesn't exist so we take whatever source has
dest[src_key] = src_value
end
else # dest isn't a hash, so we overwrite it completely
dest = source
end
end
when Array
if dest.kind_of?(Array)
dest = dest | source
else
dest = source
end
when String
dest = source
else # src_hash is not an array or hash, so we'll have to overwrite dest
dest = source
end
dest
end # deep_merge!
end
end
end
|