chef-zero 1.4.0.alpha-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +201 -0
- data/README.md +145 -0
- data/Rakefile +11 -0
- data/bin/chef-zero +43 -0
- data/lib/chef_zero.rb +7 -0
- data/lib/chef_zero/cookbook_data.rb +223 -0
- data/lib/chef_zero/data_normalizer.rb +142 -0
- data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -0
- data/lib/chef_zero/data_store/data_error.rb +31 -0
- data/lib/chef_zero/data_store/data_not_found_error.rb +29 -0
- data/lib/chef_zero/data_store/memory_store.rb +167 -0
- data/lib/chef_zero/endpoints/actor_endpoint.rb +68 -0
- data/lib/chef_zero/endpoints/actors_endpoint.rb +32 -0
- data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +25 -0
- data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -0
- data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +110 -0
- data/lib/chef_zero/endpoints/cookbooks_base.rb +65 -0
- data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -0
- data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -0
- data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -0
- data/lib/chef_zero/endpoints/data_bags_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -0
- data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +109 -0
- data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -0
- data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -0
- data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -0
- data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/node_endpoint.rb +17 -0
- data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -0
- data/lib/chef_zero/endpoints/principal_endpoint.rb +30 -0
- data/lib/chef_zero/endpoints/rest_list_endpoint.rb +40 -0
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +61 -0
- data/lib/chef_zero/endpoints/role_endpoint.rb +16 -0
- data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -0
- data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -0
- data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +51 -0
- data/lib/chef_zero/endpoints/search_endpoint.rb +188 -0
- data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -0
- data/lib/chef_zero/log.rb +7 -0
- data/lib/chef_zero/rest_base.rb +133 -0
- data/lib/chef_zero/rest_error_response.rb +11 -0
- data/lib/chef_zero/rest_request.rb +56 -0
- data/lib/chef_zero/rest_router.rb +44 -0
- data/lib/chef_zero/rspec.rb +107 -0
- data/lib/chef_zero/server.rb +309 -0
- data/lib/chef_zero/solr/query/binary_operator.rb +53 -0
- data/lib/chef_zero/solr/query/phrase.rb +23 -0
- data/lib/chef_zero/solr/query/range_query.rb +34 -0
- data/lib/chef_zero/solr/query/regexpable_query.rb +29 -0
- data/lib/chef_zero/solr/query/subquery.rb +35 -0
- data/lib/chef_zero/solr/query/term.rb +45 -0
- data/lib/chef_zero/solr/query/unary_operator.rb +43 -0
- data/lib/chef_zero/solr/solr_doc.rb +62 -0
- data/lib/chef_zero/solr/solr_parser.rb +193 -0
- data/lib/chef_zero/version.rb +3 -0
- data/spec/run.rb +25 -0
- data/spec/support/pedant.rb +117 -0
- data/spec/support/stickywicket.pem +27 -0
- metadata +204 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'chef_zero/server'
|
3
|
+
require 'chef_zero/rest_request'
|
4
|
+
|
5
|
+
module ChefZero
|
6
|
+
module RSpec
|
7
|
+
def self.server
|
8
|
+
@server
|
9
|
+
end
|
10
|
+
def self.server=(value)
|
11
|
+
@server = value
|
12
|
+
end
|
13
|
+
def self.client_key
|
14
|
+
@client_key
|
15
|
+
end
|
16
|
+
def self.client_key=(value)
|
17
|
+
@client_key = value
|
18
|
+
end
|
19
|
+
def self.request_log
|
20
|
+
@request_log ||= []
|
21
|
+
end
|
22
|
+
def self.clear_request_log
|
23
|
+
@request_log = []
|
24
|
+
end
|
25
|
+
|
26
|
+
def when_the_chef_server(description, *tags, &block)
|
27
|
+
context "When the Chef server #{description}", *tags do
|
28
|
+
before :each do
|
29
|
+
unless ChefZero::RSpec.server
|
30
|
+
# Set up configuration so that clients will point to the server
|
31
|
+
ChefZero::RSpec.server = ChefZero::Server.new(:port => 8889, :signals => false, :log_requests => true)
|
32
|
+
ChefZero::RSpec.client_key = Tempfile.new(['chef_zero_client_key', '.pem'])
|
33
|
+
ChefZero::RSpec.client_key.write(ChefZero::PRIVATE_KEY)
|
34
|
+
ChefZero::RSpec.client_key.close
|
35
|
+
# Start the server
|
36
|
+
ChefZero::RSpec.server.start_background
|
37
|
+
ChefZero::RSpec.server.on_response do |request, response|
|
38
|
+
ChefZero::RSpec.request_log << [ request, response ]
|
39
|
+
end
|
40
|
+
else
|
41
|
+
ChefZero::RSpec.server.clear_data
|
42
|
+
end
|
43
|
+
ChefZero::RSpec.clear_request_log
|
44
|
+
|
45
|
+
if defined?(Chef::Config)
|
46
|
+
@old_chef_server_url = Chef::Config.chef_server_url
|
47
|
+
@old_node_name = Chef::Config.node_name
|
48
|
+
@old_client_key = Chef::Config.client_key
|
49
|
+
Chef::Config.chef_server_url = ChefZero::RSpec.server.url
|
50
|
+
Chef::Config.node_name = 'admin'
|
51
|
+
Chef::Config.client_key = ChefZero::RSpec.client_key.path
|
52
|
+
Chef::Config.http_retry_count = 0
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if defined?(Chef::Config)
|
57
|
+
after :each do
|
58
|
+
Chef::Config.chef_server_url = @old_chef_server_url
|
59
|
+
Chef::Config.node_name = @old_node_name
|
60
|
+
Chef::Config.client_key = @old_client_key
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.client(name, client)
|
65
|
+
before(:each) { ChefZero::RSpec.server.load_data({ 'clients' => { name => client }}) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.cookbook(name, version, cookbook, options = {})
|
69
|
+
before(:each) { ChefZero::RSpec.server.load_data({ 'cookbooks' => { "#{name}-#{version}" => cookbook.merge(options) }}) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.data_bag(name, data_bag)
|
73
|
+
before(:each) { ChefZero::RSpec.server.load_data({ 'data' => { name => data_bag }}) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.environment(name, environment)
|
77
|
+
before(:each) { ChefZero::RSpec.server.load_data({ 'environments' => { name => environment }}) }
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.node(name, node)
|
81
|
+
before(:each) { ChefZero::RSpec.server.load_data({ 'nodes' => { name => node }}) }
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.role(name, role)
|
85
|
+
before(:each) { ChefZero::RSpec.server.load_data({ 'roles' => { name => role }}) }
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.user(name, user)
|
89
|
+
before(:each) { ChefZero::RSpec.server.load_data({ 'users' => { name => user }}) }
|
90
|
+
end
|
91
|
+
|
92
|
+
# after :each do
|
93
|
+
# if @@ChefZero::RSpec.server
|
94
|
+
# @@ChefZero::RSpec.server.stop
|
95
|
+
# @@ChefZero::RSpec.server = nil
|
96
|
+
# end
|
97
|
+
# if @@ChefZero::RSpec.client_key
|
98
|
+
# @@ChefZero::RSpec.client_key.unlink
|
99
|
+
# @@ChefZero::RSpec.client_key = nil
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
|
103
|
+
instance_eval(&block)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,309 @@
|
|
1
|
+
#
|
2
|
+
# Author:: John Keiser (<jkeiser@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'openssl'
|
20
|
+
require 'puma'
|
21
|
+
require 'rubygems'
|
22
|
+
require 'timeout'
|
23
|
+
|
24
|
+
require 'chef_zero'
|
25
|
+
require 'chef_zero/cookbook_data'
|
26
|
+
require 'chef_zero/rest_router'
|
27
|
+
require 'chef_zero/data_store/memory_store'
|
28
|
+
require 'chef_zero/version'
|
29
|
+
|
30
|
+
require 'chef_zero/endpoints/authenticate_user_endpoint'
|
31
|
+
require 'chef_zero/endpoints/actors_endpoint'
|
32
|
+
require 'chef_zero/endpoints/actor_endpoint'
|
33
|
+
require 'chef_zero/endpoints/cookbooks_endpoint'
|
34
|
+
require 'chef_zero/endpoints/cookbook_endpoint'
|
35
|
+
require 'chef_zero/endpoints/cookbook_version_endpoint'
|
36
|
+
require 'chef_zero/endpoints/data_bags_endpoint'
|
37
|
+
require 'chef_zero/endpoints/data_bag_endpoint'
|
38
|
+
require 'chef_zero/endpoints/data_bag_item_endpoint'
|
39
|
+
require 'chef_zero/endpoints/rest_list_endpoint'
|
40
|
+
require 'chef_zero/endpoints/environment_endpoint'
|
41
|
+
require 'chef_zero/endpoints/environment_cookbooks_endpoint'
|
42
|
+
require 'chef_zero/endpoints/environment_cookbook_endpoint'
|
43
|
+
require 'chef_zero/endpoints/environment_cookbook_versions_endpoint'
|
44
|
+
require 'chef_zero/endpoints/environment_nodes_endpoint'
|
45
|
+
require 'chef_zero/endpoints/environment_recipes_endpoint'
|
46
|
+
require 'chef_zero/endpoints/environment_role_endpoint'
|
47
|
+
require 'chef_zero/endpoints/node_endpoint'
|
48
|
+
require 'chef_zero/endpoints/principal_endpoint'
|
49
|
+
require 'chef_zero/endpoints/role_endpoint'
|
50
|
+
require 'chef_zero/endpoints/role_environments_endpoint'
|
51
|
+
require 'chef_zero/endpoints/sandboxes_endpoint'
|
52
|
+
require 'chef_zero/endpoints/sandbox_endpoint'
|
53
|
+
require 'chef_zero/endpoints/searches_endpoint'
|
54
|
+
require 'chef_zero/endpoints/search_endpoint'
|
55
|
+
require 'chef_zero/endpoints/file_store_file_endpoint'
|
56
|
+
require 'chef_zero/endpoints/not_found_endpoint'
|
57
|
+
|
58
|
+
module ChefZero
|
59
|
+
class Server
|
60
|
+
DEFAULT_OPTIONS = {
|
61
|
+
:host => '127.0.0.1',
|
62
|
+
:port => 8889,
|
63
|
+
:log_level => :info,
|
64
|
+
:generate_real_keys => true
|
65
|
+
}.freeze
|
66
|
+
|
67
|
+
def initialize(options = {})
|
68
|
+
options = DEFAULT_OPTIONS.merge(options)
|
69
|
+
@url = "http://#{options[:host]}:#{options[:port]}"
|
70
|
+
@generate_real_keys = options[:generate_real_keys]
|
71
|
+
|
72
|
+
ChefZero::Log.level = options[:log_level].to_sym
|
73
|
+
|
74
|
+
@server = Puma::Server.new(make_app, Puma::Events.new(STDERR, STDOUT))
|
75
|
+
@server.add_tcp_listener(options[:host], options[:port])
|
76
|
+
|
77
|
+
@data_store = options[:data_store] || DataStore::MemoryStore.new
|
78
|
+
end
|
79
|
+
|
80
|
+
attr_reader :server
|
81
|
+
attr_reader :data_store
|
82
|
+
attr_reader :url
|
83
|
+
|
84
|
+
include ChefZero::Endpoints
|
85
|
+
|
86
|
+
def start(options = {})
|
87
|
+
if options[:publish]
|
88
|
+
puts ">> Starting Chef Zero (v#{ChefZero::VERSION})..."
|
89
|
+
puts ">> Puma (v#{Puma::Const::PUMA_VERSION}) is listening at #{url}"
|
90
|
+
puts ">> Press CTRL+C to stop"
|
91
|
+
end
|
92
|
+
|
93
|
+
begin
|
94
|
+
thread = server.run.join
|
95
|
+
rescue Object, Interrupt
|
96
|
+
puts "\n>> Stopping Puma..."
|
97
|
+
server.stop(true) if running?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def start_background(wait = 5)
|
102
|
+
@thread = Thread.new {
|
103
|
+
begin
|
104
|
+
start
|
105
|
+
rescue
|
106
|
+
@server_error = $!
|
107
|
+
ChefZero::Log.error("#{$!.message}\n#{$!.backtrace.join("\n")}")
|
108
|
+
end
|
109
|
+
}
|
110
|
+
|
111
|
+
# Wait x seconds to make sure the server actually started
|
112
|
+
Timeout::timeout(wait) {
|
113
|
+
sleep(0.01) until running? || @server_error
|
114
|
+
raise @server_error if @server_error
|
115
|
+
}
|
116
|
+
|
117
|
+
# Give the user the thread, just in case they want it
|
118
|
+
@thread
|
119
|
+
end
|
120
|
+
|
121
|
+
def running?
|
122
|
+
!!server.running
|
123
|
+
end
|
124
|
+
|
125
|
+
def stop(wait = 5)
|
126
|
+
if @thread
|
127
|
+
@thread.join(wait)
|
128
|
+
else
|
129
|
+
server.stop(true)
|
130
|
+
end
|
131
|
+
rescue
|
132
|
+
ChefZero::Log.error "Server did not stop within #{wait} seconds. Killing..."
|
133
|
+
@thread.kill if @thread
|
134
|
+
ensure
|
135
|
+
@thread = nil
|
136
|
+
end
|
137
|
+
|
138
|
+
def gen_key_pair
|
139
|
+
if generate_real_keys?
|
140
|
+
private_key = OpenSSL::PKey::RSA.new(2048)
|
141
|
+
public_key = private_key.public_key.to_s
|
142
|
+
public_key.sub!(/^-----BEGIN RSA PUBLIC KEY-----/, '-----BEGIN PUBLIC KEY-----')
|
143
|
+
public_key.sub!(/-----END RSA PUBLIC KEY-----(\s+)$/, '-----END PUBLIC KEY-----\1')
|
144
|
+
[private_key.to_s, public_key]
|
145
|
+
else
|
146
|
+
[PRIVATE_KEY, PUBLIC_KEY]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def on_request(&block)
|
151
|
+
@on_request_proc = block
|
152
|
+
end
|
153
|
+
|
154
|
+
def on_response(&block)
|
155
|
+
@on_response_proc = block
|
156
|
+
end
|
157
|
+
|
158
|
+
# Load data in a nice, friendly form:
|
159
|
+
# {
|
160
|
+
# 'roles' => {
|
161
|
+
# 'desert' => '{ "description": "Hot and dry"' },
|
162
|
+
# 'rainforest' => { "description" => 'Wet and humid' }
|
163
|
+
# },
|
164
|
+
# 'cookbooks' => {
|
165
|
+
# 'apache2-1.0.1' => {
|
166
|
+
# 'templates' => { 'default' => { 'blah.txt' => 'hi' }}
|
167
|
+
# 'recipes' => { 'default.rb' => 'template "blah.txt"' }
|
168
|
+
# 'metadata.rb' => 'depends "mysql"'
|
169
|
+
# },
|
170
|
+
# 'apache2-1.2.0' => {
|
171
|
+
# 'templates' => { 'default' => { 'blah.txt' => 'lo' }}
|
172
|
+
# 'recipes' => { 'default.rb' => 'template "blah.txt"' }
|
173
|
+
# 'metadata.rb' => 'depends "mysql"'
|
174
|
+
# },
|
175
|
+
# 'mysql' => {
|
176
|
+
# 'recipes' => { 'default.rb' => 'file { contents "hi" }' },
|
177
|
+
# 'metadata.rb' => 'version "1.0.0"'
|
178
|
+
# }
|
179
|
+
# }
|
180
|
+
# }
|
181
|
+
def load_data(contents)
|
182
|
+
%w(clients environments nodes roles users).each do |data_type|
|
183
|
+
if contents[data_type]
|
184
|
+
dejsonize_children(contents[data_type]).each_pair do |name, data|
|
185
|
+
data_store.set([data_type, name], data, :create)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
if contents['data']
|
190
|
+
contents['data'].each_pair do |key, data_bag|
|
191
|
+
data_store.create_dir(['data'], key, :recursive)
|
192
|
+
dejsonize_children(data_bag).each do |item_name, item|
|
193
|
+
data_store.set(['data', key, item_name], item, :create)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
if contents['cookbooks']
|
198
|
+
contents['cookbooks'].each_pair do |name_version, cookbook|
|
199
|
+
if name_version =~ /(.+)-(\d+\.\d+\.\d+)$/
|
200
|
+
cookbook_data = CookbookData.to_hash(cookbook, $1, $2)
|
201
|
+
else
|
202
|
+
cookbook_data = CookbookData.to_hash(cookbook, name_version)
|
203
|
+
end
|
204
|
+
raise "No version specified" if !cookbook_data[:version]
|
205
|
+
data_store.create_dir(['cookbooks'], cookbook_data[:cookbook_name], :recursive)
|
206
|
+
data_store.set(['cookbooks', cookbook_data[:cookbook_name], cookbook_data[:version]], JSON.pretty_generate(cookbook_data), :create)
|
207
|
+
cookbook_data.values.each do |files|
|
208
|
+
next unless files.is_a? Array
|
209
|
+
files.each do |file|
|
210
|
+
data_store.set(['file_store', 'checksums', file[:checksum]], get_file(cookbook, file[:path]), :create)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def clear_data
|
218
|
+
@data_store.clear
|
219
|
+
end
|
220
|
+
|
221
|
+
def request_handler(&block)
|
222
|
+
@request_handler = block
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
def make_app
|
228
|
+
router = RestRouter.new([
|
229
|
+
[ '/authenticate_user', AuthenticateUserEndpoint.new(self) ],
|
230
|
+
[ '/clients', ActorsEndpoint.new(self) ],
|
231
|
+
[ '/clients/*', ActorEndpoint.new(self) ],
|
232
|
+
[ '/cookbooks', CookbooksEndpoint.new(self) ],
|
233
|
+
[ '/cookbooks/*', CookbookEndpoint.new(self) ],
|
234
|
+
[ '/cookbooks/*/*', CookbookVersionEndpoint.new(self) ],
|
235
|
+
[ '/data', DataBagsEndpoint.new(self) ],
|
236
|
+
[ '/data/*', DataBagEndpoint.new(self) ],
|
237
|
+
[ '/data/*/*', DataBagItemEndpoint.new(self) ],
|
238
|
+
[ '/environments', RestListEndpoint.new(self) ],
|
239
|
+
[ '/environments/*', EnvironmentEndpoint.new(self) ],
|
240
|
+
[ '/environments/*/cookbooks', EnvironmentCookbooksEndpoint.new(self) ],
|
241
|
+
[ '/environments/*/cookbooks/*', EnvironmentCookbookEndpoint.new(self) ],
|
242
|
+
[ '/environments/*/cookbook_versions', EnvironmentCookbookVersionsEndpoint.new(self) ],
|
243
|
+
[ '/environments/*/nodes', EnvironmentNodesEndpoint.new(self) ],
|
244
|
+
[ '/environments/*/recipes', EnvironmentRecipesEndpoint.new(self) ],
|
245
|
+
[ '/environments/*/roles/*', EnvironmentRoleEndpoint.new(self) ],
|
246
|
+
[ '/nodes', RestListEndpoint.new(self) ],
|
247
|
+
[ '/nodes/*', NodeEndpoint.new(self) ],
|
248
|
+
[ '/principals/*', PrincipalEndpoint.new(self) ],
|
249
|
+
[ '/roles', RestListEndpoint.new(self) ],
|
250
|
+
[ '/roles/*', RoleEndpoint.new(self) ],
|
251
|
+
[ '/roles/*/environments', RoleEnvironmentsEndpoint.new(self) ],
|
252
|
+
[ '/roles/*/environments/*', EnvironmentRoleEndpoint.new(self) ],
|
253
|
+
[ '/sandboxes', SandboxesEndpoint.new(self) ],
|
254
|
+
[ '/sandboxes/*', SandboxEndpoint.new(self) ],
|
255
|
+
[ '/search', SearchesEndpoint.new(self) ],
|
256
|
+
[ '/search/*', SearchEndpoint.new(self) ],
|
257
|
+
[ '/users', ActorsEndpoint.new(self) ],
|
258
|
+
[ '/users/*', ActorEndpoint.new(self) ],
|
259
|
+
|
260
|
+
[ '/file_store/**', FileStoreFileEndpoint.new(self) ],
|
261
|
+
])
|
262
|
+
router.not_found = NotFoundEndpoint.new
|
263
|
+
|
264
|
+
return proc do |env|
|
265
|
+
request = RestRequest.new(env)
|
266
|
+
if @on_request_proc
|
267
|
+
@on_request_proc.call(request)
|
268
|
+
end
|
269
|
+
response = nil
|
270
|
+
if @request_handler
|
271
|
+
response = @request_handler.call(request)
|
272
|
+
end
|
273
|
+
unless response
|
274
|
+
response = router.call(request)
|
275
|
+
end
|
276
|
+
if @on_response_proc
|
277
|
+
@on_response_proc.call(request, response)
|
278
|
+
end
|
279
|
+
|
280
|
+
# Puma expects the response to be an array (chunked responses). Since
|
281
|
+
# we are statically generating data, we won't ever have said chunked
|
282
|
+
# response, so fake it.
|
283
|
+
response[-1] = Array(response[-1])
|
284
|
+
|
285
|
+
response
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def dejsonize_children(hash)
|
290
|
+
result = {}
|
291
|
+
hash.each_pair do |key, value|
|
292
|
+
result[key] = value.is_a?(Hash) ? JSON.pretty_generate(value) : value
|
293
|
+
end
|
294
|
+
result
|
295
|
+
end
|
296
|
+
|
297
|
+
def get_file(directory, path)
|
298
|
+
value = directory
|
299
|
+
path.split('/').each do |part|
|
300
|
+
value = value[part]
|
301
|
+
end
|
302
|
+
value
|
303
|
+
end
|
304
|
+
|
305
|
+
def generate_real_keys?
|
306
|
+
!!@generate_real_keys
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ChefZero
|
2
|
+
module Solr
|
3
|
+
module Query
|
4
|
+
class BinaryOperator
|
5
|
+
def initialize(left, operator, right)
|
6
|
+
@left = left
|
7
|
+
@operator = operator
|
8
|
+
@right = right
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"(#{left} #{operator} #{right})"
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :left
|
16
|
+
attr_reader :operator
|
17
|
+
attr_reader :right
|
18
|
+
|
19
|
+
def matches_doc?(doc)
|
20
|
+
case @operator
|
21
|
+
when 'AND'
|
22
|
+
left.matches_doc?(doc) && right.matches_doc?(doc)
|
23
|
+
when 'OR'
|
24
|
+
left.matches_doc?(doc) || right.matches_doc?(doc)
|
25
|
+
when '^'
|
26
|
+
left.matches_doc?(doc)
|
27
|
+
when ':'
|
28
|
+
if left.respond_to?(:literal_string) && left.literal_string
|
29
|
+
value = doc[left.literal_string]
|
30
|
+
right.matches_values?([value])
|
31
|
+
else
|
32
|
+
values = doc.matching_values { |key| left.matches_values?([key]) }
|
33
|
+
right.matches_values?(values)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def matches_values?(values)
|
39
|
+
case @operator
|
40
|
+
when 'AND'
|
41
|
+
left.matches_values?(values) && right.matches_values?(values)
|
42
|
+
when 'OR'
|
43
|
+
left.matches_values?(values) || right.matches_values?(values)
|
44
|
+
when '^'
|
45
|
+
left.matches_values?(values)
|
46
|
+
when ':'
|
47
|
+
raise ": does not work inside a : or term"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|