erchef-solr 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +201 -0
- data/README.rdoc +0 -0
- data/Rakefile +66 -0
- data/bin/chef-solr +27 -0
- data/bin/chef-solr-installer +26 -0
- data/lib/chef/solr.rb +1 -0
- data/lib/chef/solr/application/solr.rb +275 -0
- data/lib/chef/solr/solr_installer.rb +386 -0
- data/lib/chef/solr/version.rb +11 -0
- data/solr/solr-home.tar.gz +0 -0
- data/solr/solr-jetty.tar.gz +0 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/unit/application/solr_spec.rb +569 -0
- metadata +78 -0
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Daniel DeLeo (<dan@opscode.com)
|
|
3
|
+
# Copyright:: Copyright (c) 2011 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
|
+
require 'pp'
|
|
19
|
+
require 'optparse'
|
|
20
|
+
require 'chef/solr/version'
|
|
21
|
+
require 'chef/shell_out'
|
|
22
|
+
require 'chef/mixin/shell_out'
|
|
23
|
+
|
|
24
|
+
class Chef
|
|
25
|
+
class SolrInstaller
|
|
26
|
+
|
|
27
|
+
class Config
|
|
28
|
+
class CompatConfig
|
|
29
|
+
def initialize
|
|
30
|
+
@config_settings = {}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def from_file(file)
|
|
34
|
+
file = File.expand_path(file)
|
|
35
|
+
if File.readable?(file)
|
|
36
|
+
instance_eval(IO.read(file), file, 1)
|
|
37
|
+
else
|
|
38
|
+
STDERR.puts "Cannot open config file #{file} default settings will be used"
|
|
39
|
+
end
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def method_missing(method_name, *args, &block)
|
|
44
|
+
if args.size == 1
|
|
45
|
+
@config_settings[method_name] = args.first
|
|
46
|
+
elsif args.empty?
|
|
47
|
+
@config_settings[method_name] or super
|
|
48
|
+
else
|
|
49
|
+
super
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_hash
|
|
54
|
+
@config_settings
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def self.default_values
|
|
60
|
+
@default_values ||= {}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.configurables
|
|
64
|
+
@configurables ||= []
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.configurable(value, default=nil)
|
|
68
|
+
configurables << value
|
|
69
|
+
attr_accessor value
|
|
70
|
+
default_values[value] = default if default
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def each_configurable
|
|
74
|
+
self.class.configurables.each do |config_param|
|
|
75
|
+
yield [config_param, send(config_param)]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
configurable :config_file, '/etc/chef/solr.rb'
|
|
80
|
+
|
|
81
|
+
# Defaults to /var/chef
|
|
82
|
+
configurable :solr_base_path, nil
|
|
83
|
+
|
|
84
|
+
def solr_base_path
|
|
85
|
+
@solr_base_path || '/var/chef'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Sets the solr_base_path. Also resets solr_home_path, solr_jetty_path,
|
|
89
|
+
# and solr_data_path.
|
|
90
|
+
def solr_base_path=(base_path)
|
|
91
|
+
@solr_home_path, @solr_jetty_path, @solr_data_path = nil,nil,nil
|
|
92
|
+
@solr_base_path = base_path
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# Computed from base path, defaults to /var/chef/solr
|
|
97
|
+
configurable :solr_home_path, nil
|
|
98
|
+
|
|
99
|
+
def solr_home_path
|
|
100
|
+
@solr_home_path || File.join(solr_base_path, 'solr')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Computed from base path, defaults to /var/chef/solr-jetty
|
|
104
|
+
configurable :solr_jetty_path, nil
|
|
105
|
+
|
|
106
|
+
def solr_jetty_path
|
|
107
|
+
@solr_jetty_path || File.join(solr_base_path, 'solr-jetty')
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Computed from base path, defaults to /var/chef/solr/data
|
|
111
|
+
configurable :solr_data_path, nil
|
|
112
|
+
|
|
113
|
+
def solr_data_path
|
|
114
|
+
@solr_data_path || File.join(solr_base_path, 'solr', 'data')
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
configurable :user, nil
|
|
119
|
+
|
|
120
|
+
configurable :group, nil
|
|
121
|
+
|
|
122
|
+
configurable :force, false
|
|
123
|
+
|
|
124
|
+
alias :force? :force
|
|
125
|
+
|
|
126
|
+
configurable :noop, false
|
|
127
|
+
|
|
128
|
+
alias :noop? :noop
|
|
129
|
+
|
|
130
|
+
def initialize
|
|
131
|
+
apply_hash(self.class.default_values)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def configure_from(argv)
|
|
135
|
+
cli_config = CLI.parse_options(argv)
|
|
136
|
+
#pp :cli_config => cli_config.to_hash
|
|
137
|
+
config_file_config = CompatConfig.new.from_file(cli_config.config_file).to_hash
|
|
138
|
+
#pp :config_file_config => config_file_config
|
|
139
|
+
apply_hash(config_file_config)
|
|
140
|
+
apply_hash(cli_config.to_hash)
|
|
141
|
+
#pp :combined_config => self.to_hash
|
|
142
|
+
self
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def to_hash
|
|
146
|
+
self.class.configurables.inject({}) do |hash, config_option|
|
|
147
|
+
value = instance_variable_get("@#{config_option}".to_sym)
|
|
148
|
+
hash[config_option] = value if value
|
|
149
|
+
hash
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def apply_hash(hash)
|
|
154
|
+
hash.each do |key, value|
|
|
155
|
+
method_for_key = "#{key}=".to_sym
|
|
156
|
+
if respond_to?(method_for_key)
|
|
157
|
+
send(method_for_key, value)
|
|
158
|
+
else
|
|
159
|
+
STDERR.puts("Configuration setting #{key} is unknown and will be ignored")
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
module CLI
|
|
165
|
+
@config = Config.new
|
|
166
|
+
|
|
167
|
+
@option_parser = OptionParser.new do |o|
|
|
168
|
+
o.banner = "Usage: chef-solr-installer [options]"
|
|
169
|
+
|
|
170
|
+
o.on('-c', '--config CONFIG_FILE', 'The configuration file to use') do |conf|
|
|
171
|
+
@config.config_file = File.expand_path(conf)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
o.on('-u', '--user USER', "User who will own Solr's data directory") do |u|
|
|
175
|
+
@config.user = u
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
o.on('-g', '--group GROUP', "Group that will own Solr's data directory") do |g|
|
|
179
|
+
@config.group = g
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
o.on('-p', '--base-path PATH', "The base path for the installation. Must be given before any -H -W or -D options") do |path|
|
|
183
|
+
@config.solr_base_path = path
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
o.on('-H', '--solr-home-dir PATH', 'Where to create the Solr home directory. Defaults to BASE_PATH/solr') do |path|
|
|
187
|
+
@config.solr_home_path = path
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
o.on('-W', '--solr-jetty-path PATH', 'Where to install Jetty for Solr. Defaults to BASE_PATH/solr-jetty ') do |path|
|
|
191
|
+
@config.solr_jetty_path = path
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
o.on('-D', '--solr-data-path PATH', 'Where to create the Solr data directory. Defaults to BASE_PATH/solr/data') do |path|
|
|
195
|
+
@config.solr_data_path = path
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
o.on('-n', '--noop', "Don't actually install, just show what would be done by the install") do
|
|
199
|
+
@config.noop = true
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
o.on('-f', '--force', 'Overwrite any existing installation without asking for confirmation') do
|
|
203
|
+
@config.force = true
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
o.on_tail('-h', '--help', 'show this message') do
|
|
207
|
+
puts "chef-solr-installer #{Chef::Solr::VERSION}"
|
|
208
|
+
puts ''
|
|
209
|
+
puts o
|
|
210
|
+
puts ''
|
|
211
|
+
puts 'Default Settings:'
|
|
212
|
+
@config.each_configurable do |param, value|
|
|
213
|
+
value_for_display = value || "none/false"
|
|
214
|
+
puts " #{param}:".ljust(20) + " #{value_for_display}"
|
|
215
|
+
end
|
|
216
|
+
exit 1
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
o.on_tail('-v', '--version', 'show the version and exit') do
|
|
220
|
+
puts "chef-solr-installer #{Chef::Solr::VERSION}"
|
|
221
|
+
exit 0
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def self.parse_options(argv)
|
|
227
|
+
@option_parser.parse!(argv.dup)
|
|
228
|
+
@config
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def self.config
|
|
232
|
+
@config
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
include Chef::Mixin::ShellOut
|
|
240
|
+
|
|
241
|
+
PACKAGED_SOLR_DIR = File.expand_path( "../../../../solr", __FILE__)
|
|
242
|
+
|
|
243
|
+
attr_reader :config
|
|
244
|
+
|
|
245
|
+
def initialize(argv)
|
|
246
|
+
@indent = 0
|
|
247
|
+
@config = Config.new.configure_from(argv.dup)
|
|
248
|
+
@overwriting = false
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def overwriting?
|
|
252
|
+
@overwriting
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def chef_solr_installed?
|
|
256
|
+
File.exist?(config.solr_home_path)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def run
|
|
260
|
+
say ''
|
|
261
|
+
say "*** DRY RUN ***" if config.noop?
|
|
262
|
+
|
|
263
|
+
if chef_solr_installed?
|
|
264
|
+
@overwriting = true
|
|
265
|
+
confirm_overwrite unless config.force? || config.noop?
|
|
266
|
+
scorch_the_earth
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
create_solr_home
|
|
270
|
+
create_solr_data_dir
|
|
271
|
+
unpack_solr_jetty
|
|
272
|
+
|
|
273
|
+
say ""
|
|
274
|
+
say "Successfully installed Chef Solr."
|
|
275
|
+
|
|
276
|
+
if overwriting?
|
|
277
|
+
say "You can restore your search index using `knife index rebuild`"
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def confirm_overwrite
|
|
282
|
+
if STDIN.tty? && STDOUT.tty?
|
|
283
|
+
say "Chef Solr is already installed in #{config.solr_home_path}"
|
|
284
|
+
print "Do you want to overwrite the current install? All existing Solr data will be lost. [y/n] "
|
|
285
|
+
unless STDIN.gets =~ /^y/
|
|
286
|
+
say "Quitting. Try running this with --noop to see what it will change."
|
|
287
|
+
exit 1
|
|
288
|
+
end
|
|
289
|
+
else
|
|
290
|
+
say(<<-FAIL)
|
|
291
|
+
ERROR: Chef Solr is already installed in #{config.solr_home_path} and you did not use the
|
|
292
|
+
--force option. Use --force to overwrite an existing installation in a non-
|
|
293
|
+
interactive terminal.
|
|
294
|
+
FAIL
|
|
295
|
+
exit 1
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def scorch_the_earth
|
|
300
|
+
group("Removing the existing Chef Solr installation") do
|
|
301
|
+
rm_rf(config.solr_home_path)
|
|
302
|
+
rm_rf(config.solr_jetty_path)
|
|
303
|
+
rm_rf(config.solr_data_path)
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def create_solr_home
|
|
308
|
+
group("Creating Solr Home Directory") do
|
|
309
|
+
mkdir_p(config.solr_home_path)
|
|
310
|
+
chdir(config.solr_home_path) do
|
|
311
|
+
sh("tar zxvf #{File.join(PACKAGED_SOLR_DIR, 'solr-home.tar.gz')}")
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def create_solr_data_dir
|
|
317
|
+
group("Creating Solr Data Directory") do
|
|
318
|
+
mkdir_p(config.solr_data_path)
|
|
319
|
+
chown(config.solr_data_path)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def unpack_solr_jetty
|
|
324
|
+
group("Unpacking Solr Jetty") do
|
|
325
|
+
mkdir_p(config.solr_jetty_path)
|
|
326
|
+
chdir(config.solr_jetty_path) do
|
|
327
|
+
sh("tar zxvf #{File.join(PACKAGED_SOLR_DIR, 'solr-jetty.tar.gz')}")
|
|
328
|
+
end
|
|
329
|
+
chown(config.solr_jetty_path)
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def mkdir_p(directory)
|
|
334
|
+
say "mkdir -p #{directory}"
|
|
335
|
+
FileUtils.mkdir_p(directory, :mode => 0755) unless config.noop?
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def chdir(dir, &block)
|
|
339
|
+
say "entering #{dir}"
|
|
340
|
+
if config.noop?
|
|
341
|
+
yield if block_given? # still call the block so we get the noop output.
|
|
342
|
+
else
|
|
343
|
+
Dir.chdir(dir) { yield if block_given? }
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def sh(*args)
|
|
348
|
+
opts = args[1, args.size - 1]
|
|
349
|
+
opts_msg = opts.empty? ? '' : " #{opts.to_s}"
|
|
350
|
+
say "#{args.first}#{opts_msg}"
|
|
351
|
+
shell_out!(*(args << {:cwd => false})) unless config.noop?
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
def chown(file)
|
|
355
|
+
if config.user
|
|
356
|
+
msg = "chown -R #{config.user}"
|
|
357
|
+
msg << ":#{config.group}" if config.group
|
|
358
|
+
msg << " #{file}"
|
|
359
|
+
say msg
|
|
360
|
+
FileUtils.chown_R(config.user, config.group, file) unless config.noop?
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def rm_rf(path)
|
|
365
|
+
say "rm -rf #{path}"
|
|
366
|
+
FileUtils.rm_rf(path) unless config.noop?
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def indent
|
|
370
|
+
@indent += 1
|
|
371
|
+
yield
|
|
372
|
+
@indent -= 1
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def group(message, &block)
|
|
376
|
+
say(message)
|
|
377
|
+
indent(&block)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def say(message)
|
|
381
|
+
puts "#{' ' * (2 * @indent)}#{message}"
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
Binary file
|
|
Binary file
|
data/spec/spec.opts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
-cbfs
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Thomas Bishop (<bishop.thomas@gmail.com>)
|
|
3
|
+
# Copyright:: Copyright (c) 2012 Thomas Bishop
|
|
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 'rspec'
|
|
20
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
|
21
|
+
$:.unshift(File.expand_path('../../lib/', __FILE__))
|
|
22
|
+
$:.unshift(File.expand_path('../../../chef/lib', __FILE__))
|
|
23
|
+
|
|
24
|
+
require 'chef/solr'
|
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Thomas Bishop (<bishop.thomas@gmail.com>)
|
|
3
|
+
# Copyright:: Copyright (c) 2012 Thomas Bishop
|
|
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 'spec_helper'
|
|
20
|
+
require 'chef/solr/application/solr'
|
|
21
|
+
|
|
22
|
+
describe Chef::Solr::Application::Solr do
|
|
23
|
+
|
|
24
|
+
describe 'initialize' do
|
|
25
|
+
it 'should have a default config_file option' do
|
|
26
|
+
subject.config[:config_file].should == '/etc/chef/solr.rb'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe 'schema_file_path' do
|
|
31
|
+
it 'should return the default schema file path' do
|
|
32
|
+
subject.schema_file_path.should == '/var/chef/solr/conf/schema.xml'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'with a custom solr home path' do
|
|
36
|
+
it 'should return the schema path' do
|
|
37
|
+
Chef::Config.stub(:[]).with(:solr_home_path).
|
|
38
|
+
and_return('/opt/chef/solr')
|
|
39
|
+
subject.schema_file_path.should == '/opt/chef/solr/conf/schema.xml'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe 'solr_config_file_path' do
|
|
46
|
+
it 'should return the default solr config path' do
|
|
47
|
+
subject.solr_config_file_path.should == '/var/chef/solr/conf/solrconfig.xml'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'with a custom solr home path' do
|
|
51
|
+
it 'should return the solr config path' do
|
|
52
|
+
Chef::Config.stub(:[]).with(:solr_home_path).
|
|
53
|
+
and_return('/opt/chef/solr')
|
|
54
|
+
subject.solr_config_file_path.should == '/opt/chef/solr/conf/solrconfig.xml'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe 'schema_document' do
|
|
61
|
+
before do
|
|
62
|
+
@schema_path = '/opt/chef/solr/conf/schema.xml'
|
|
63
|
+
subject.stub :schema_file_path => @schema_path
|
|
64
|
+
@doc_contents = '<?xml version="1.0" encoding="UTF-8" ?><foo>bar</foo>'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'should read the schema file at the correct path' do
|
|
68
|
+
REXML::Document.stub(:new)
|
|
69
|
+
File.should_receive(:open).with(@schema_path, 'r').
|
|
70
|
+
and_yield(@doc_contents)
|
|
71
|
+
subject.schema_document
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'should return the schema' do
|
|
75
|
+
File.stub(:open).and_yield(@doc_contents)
|
|
76
|
+
subject.schema_document.should be_a REXML::Document
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe 'config_document' do
|
|
81
|
+
before do
|
|
82
|
+
@solr_config_path = '/opt/chef/solr/conf/solrconfig.xml'
|
|
83
|
+
subject.stub :solr_config_file_path => @solr_config_path
|
|
84
|
+
@doc_contents = '<?xml version="1.0" encoding="UTF-8" ?><foo>bar</foo>'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'should read the config file at the correct path' do
|
|
88
|
+
REXML::Document.stub(:new)
|
|
89
|
+
File.should_receive(:open).with(@solr_config_path, 'r').
|
|
90
|
+
and_yield(@doc_contents)
|
|
91
|
+
subject.config_document
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should return an REXML document' do
|
|
95
|
+
File.stub(:open).and_yield(@doc_contents)
|
|
96
|
+
subject.config_document.should be_a REXML::Document
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
describe 'schema_attributes' do
|
|
101
|
+
it 'should return the attributes of the schema element' do
|
|
102
|
+
schema_doc_contents = '<?xml version="1.0" encoding="UTF-8" ?>'
|
|
103
|
+
schema_doc_contents << '<schema name="chef" version="1.2"></schema>'
|
|
104
|
+
subject.stub(:schema_document).
|
|
105
|
+
and_return(REXML::Document.new(schema_doc_contents))
|
|
106
|
+
|
|
107
|
+
subject.schema_attributes["name"].should == 'chef'
|
|
108
|
+
subject.schema_attributes["version"].should == '1.2'
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe 'solr_main_index_elements' do
|
|
113
|
+
before do
|
|
114
|
+
doc_contents = '<?xml version="1.0" encoding="UTF-8" ?>'
|
|
115
|
+
doc_contents << '<config><mainIndex>'
|
|
116
|
+
doc_contents << '<maxFieldLength>10000</maxFieldLength>'
|
|
117
|
+
doc_contents << '</mainIndex></config>'
|
|
118
|
+
subject.stub(:config_document).
|
|
119
|
+
and_return(REXML::Document.new(doc_contents))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'should return a collection of the REXML elements' do
|
|
123
|
+
subject.solr_main_index_elements.each { |e| e.should be_a REXML::Element }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'should return the correct elements' do
|
|
127
|
+
subject.solr_main_index_elements.first.name.should == 'maxFieldLength'
|
|
128
|
+
subject.solr_main_index_elements.first.text.should == '10000'
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
describe 'solr_schema_name' do
|
|
133
|
+
it 'should return the schema name' do
|
|
134
|
+
subject.stub :schema_attributes => { 'name' => 'chef' }
|
|
135
|
+
subject.solr_schema_name.should == 'chef'
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe 'solr_schema_version' do
|
|
140
|
+
it 'should return the schema version' do
|
|
141
|
+
subject.stub :schema_attributes => { 'version' => '1.2' }
|
|
142
|
+
subject.solr_schema_version.should == '1.2'
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
describe 'solr_main_index_max_field_length' do
|
|
147
|
+
before do
|
|
148
|
+
@elements = [ REXML::Element.new('useCompoundFile').add_text('false'),
|
|
149
|
+
REXML::Element.new('ramBufferSizeMB').add_text('32'),
|
|
150
|
+
REXML::Element.new('maxFieldLength').add_text('10000') ]
|
|
151
|
+
subject.stub :solr_main_index_elements => @elements
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'should return the value of maxFieldLimit as an integer' do
|
|
155
|
+
subject.solr_main_index_max_field_length.should == 10000
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context 'if unable to find the maxFieldLimit' do
|
|
159
|
+
before do
|
|
160
|
+
elements = @elements.select { |e| e.name != 'maxFieldLength' }
|
|
161
|
+
subject.stub :solr_main_index_elements => elements
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it 'should return nil' do
|
|
165
|
+
subject.solr_main_index_max_field_length.should be_nil
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
describe 'valid_schema_name?' do
|
|
172
|
+
it 'should return true if the schema name matches' do
|
|
173
|
+
subject.stub :solr_schema_name => Chef::Solr::SCHEMA_NAME
|
|
174
|
+
subject.valid_schema_name?.should be_true
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it 'should return false if the schema name does not match' do
|
|
178
|
+
subject.stub :solr_schema_name => 'foo'
|
|
179
|
+
subject.valid_schema_name?.should be_false
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
describe 'valid_schema_version?' do
|
|
184
|
+
it 'should return true if the version name matches' do
|
|
185
|
+
subject.stub :solr_schema_version => Chef::Solr::SCHEMA_VERSION
|
|
186
|
+
subject.valid_schema_version?.should be_true
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it 'should return false if the version name does not match' do
|
|
190
|
+
subject.stub :solr_schema_version => '-1.0'
|
|
191
|
+
subject.valid_schema_version?.should be_false
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
describe 'check_value_of_main_index_max_field_length' do
|
|
196
|
+
it 'should log a warning if it is set to <= 10000' do
|
|
197
|
+
subject.stub :solr_main_index_max_field_length => 10000
|
|
198
|
+
pattern = /maxFieldLimit.+set to.+recommended to increase this value/
|
|
199
|
+
Chef::Log.should_receive(:warn).with(pattern)
|
|
200
|
+
subject.check_value_of_main_index_max_field_length
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'should not log a warning if it is set to > 10000' do
|
|
204
|
+
subject.stub :solr_main_index_max_field_length => 10001
|
|
205
|
+
Chef::Log.should_not_receive(:warn)
|
|
206
|
+
subject.check_value_of_main_index_max_field_length
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
context 'if it is not set' do
|
|
210
|
+
it 'should log a warning if it is not set' do
|
|
211
|
+
subject.stub :solr_main_index_max_field_length => nil
|
|
212
|
+
Chef::Log.should_receive(:warn).
|
|
213
|
+
with(/Unable to determine the maxFieldLimit for the mainIndex/)
|
|
214
|
+
subject.check_value_of_main_index_max_field_length
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
describe 'solr_home_exists?' do
|
|
221
|
+
before do
|
|
222
|
+
Chef::Config.stub(:[]).with(:solr_home_path).
|
|
223
|
+
and_return('/opt/chef/solr')
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it 'should return true if the solr home exists' do
|
|
227
|
+
File.stub(:directory?).with('/opt/chef/solr').
|
|
228
|
+
and_return(true)
|
|
229
|
+
subject.solr_home_exist?.should be_true
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it 'should return false if the solr home does not exist' do
|
|
233
|
+
File.stub(:directory?).with('/opt/chef/solr').
|
|
234
|
+
and_return(false)
|
|
235
|
+
subject.solr_home_exist?.should be_false
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
describe 'solr_data_dir_exists?' do
|
|
240
|
+
before do
|
|
241
|
+
Chef::Config.stub(:[]).with(:solr_data_path).
|
|
242
|
+
and_return('/opt/chef/solr')
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it 'should return true if the solr data dir exists' do
|
|
246
|
+
File.stub(:directory?).with('/opt/chef/solr').
|
|
247
|
+
and_return(true)
|
|
248
|
+
subject.solr_data_dir_exist?.should be_true
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it 'should return false if the solr data dir does not exist' do
|
|
252
|
+
File.stub(:directory?).with('/opt/chef/solr').
|
|
253
|
+
and_return(false)
|
|
254
|
+
subject.solr_data_dir_exist?.should be_false
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
describe 'solr_jetty_home_exists?' do
|
|
259
|
+
before do
|
|
260
|
+
Chef::Config.stub(:[]).with(:solr_jetty_path).
|
|
261
|
+
and_return('/opt/chef/solr')
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it 'should return true if the solr jetty dir exists' do
|
|
265
|
+
File.stub(:directory?).with('/opt/chef/solr').
|
|
266
|
+
and_return(true)
|
|
267
|
+
subject.solr_jetty_home_exist?.should be_true
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it 'should return false if the solr jetty dir does not exist' do
|
|
271
|
+
File.stub(:directory?).with('/opt/chef/solr').
|
|
272
|
+
and_return(false)
|
|
273
|
+
subject.solr_jetty_home_exist?.should be_false
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
describe 'assert_solr_installed!' do
|
|
278
|
+
|
|
279
|
+
context 'when unsuccessful' do
|
|
280
|
+
before do
|
|
281
|
+
message = /chef solr is not installed.+home.+data.+jetty.+misconfigured/i
|
|
282
|
+
Chef::Log.should_receive(:fatal).with(message).and_return(true)
|
|
283
|
+
Chef::Log.stub(:fatal)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
context 'because the solr home does not exist' do
|
|
287
|
+
before do
|
|
288
|
+
subject.stub :solr_home_exist? => false
|
|
289
|
+
subject.stub :solr_data_dir_exist => true
|
|
290
|
+
subject.stub :solr_jetty_home_exist => true
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
it 'should log messages and exit' do
|
|
294
|
+
lambda {
|
|
295
|
+
subject.assert_solr_installed!
|
|
296
|
+
}.should raise_error SystemExit
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
context 'because the solr data dir does not exist' do
|
|
301
|
+
before do
|
|
302
|
+
subject.stub :solr_home_exist? => true
|
|
303
|
+
subject.stub :solr_data_dir_exist => false
|
|
304
|
+
subject.stub :solr_jetty_home_exist => true
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
it 'should log messages and exit' do
|
|
308
|
+
lambda {
|
|
309
|
+
subject.assert_solr_installed!
|
|
310
|
+
}.should raise_error SystemExit
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
context 'because the solr jetty home does not exist' do
|
|
315
|
+
before do
|
|
316
|
+
subject.stub :solr_home_exist? => true
|
|
317
|
+
subject.stub :solr_data_dir_exist => true
|
|
318
|
+
subject.stub :solr_jetty_home_exist => false
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it 'should log messages and exit' do
|
|
322
|
+
lambda {
|
|
323
|
+
subject.assert_solr_installed!
|
|
324
|
+
}.should raise_error SystemExit
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
context 'when solr home, data dir, and jetty home exist' do
|
|
331
|
+
before do
|
|
332
|
+
['home', 'data_dir', 'jetty_home'].each do |item|
|
|
333
|
+
subject.stub "solr_#{item}_exist?".to_sym => true
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
it 'should not exit' do
|
|
338
|
+
subject.assert_solr_installed!.should_not raise_error SystemExit
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
describe 'assert_valid_schema!' do
|
|
345
|
+
context 'when unsuccessful' do
|
|
346
|
+
before do
|
|
347
|
+
message = /chef solr installation.+upgraded.+/i
|
|
348
|
+
Chef::Log.should_receive(:fatal).with(message).and_return(true)
|
|
349
|
+
Chef::Log.stub(:fatal)
|
|
350
|
+
subject.stub :solr_schema_version => ''
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
context 'because the schema name is not valid' do
|
|
354
|
+
before do
|
|
355
|
+
subject.stub :valid_schema_name? => false
|
|
356
|
+
subject.stub :valid_schema_version => true
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
it 'should log messages and exit' do
|
|
360
|
+
lambda {
|
|
361
|
+
subject.assert_valid_schema!
|
|
362
|
+
}.should raise_error SystemExit
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
context 'because the schema version is not valid' do
|
|
367
|
+
before do
|
|
368
|
+
subject.stub :valid_schema_name? => true
|
|
369
|
+
subject.stub :valid_schema_version => false
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it 'should log messages and exit' do
|
|
373
|
+
lambda {
|
|
374
|
+
subject.assert_valid_schema!
|
|
375
|
+
}.should raise_error SystemExit
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
context 'when the schema name and version are valid' do
|
|
382
|
+
before do
|
|
383
|
+
['name', 'version'].each do |item|
|
|
384
|
+
subject.stub "valid_schema_#{item}?".to_sym => true
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
it 'should not exit' do
|
|
389
|
+
subject.assert_valid_schema!.should_not raise_error SystemExit
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
describe 'setup_application' do
|
|
396
|
+
before do
|
|
397
|
+
Chef::Daemon.should_receive :change_privilege
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it 'should see if solr is installed' do
|
|
401
|
+
subject.stub :assert_valid_schema!
|
|
402
|
+
subject.stub :check_value_of_main_index_max_field_length
|
|
403
|
+
subject.should_receive :assert_solr_installed!
|
|
404
|
+
subject.setup_application
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
it 'should see if the schema is valid' do
|
|
408
|
+
subject.stub :assert_solr_installed!
|
|
409
|
+
subject.stub :check_value_of_main_index_max_field_length
|
|
410
|
+
subject.should_receive :assert_valid_schema!
|
|
411
|
+
subject.setup_application
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
it 'should check the maxFieldLimit setting' do
|
|
415
|
+
subject.stub :assert_solr_installed!
|
|
416
|
+
subject.stub :assert_valid_schema!
|
|
417
|
+
subject.should_receive :check_value_of_main_index_max_field_length
|
|
418
|
+
subject.setup_application
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
context 'with solr installed and a valid schema' do
|
|
422
|
+
before do
|
|
423
|
+
subject.stub :assert_solr_installed!
|
|
424
|
+
subject.stub :assert_valid_schema!
|
|
425
|
+
subject.stub :check_value_of_main_index_max_field_length
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
context 'with -L or --logfile' do
|
|
429
|
+
before do
|
|
430
|
+
@log_location = '/var/log/chef_solr.log'
|
|
431
|
+
Chef::Config.stub(:[]).with(:log_location).and_return(@log_location)
|
|
432
|
+
Chef::Config.stub(:[]).with(:log_level).and_return(:info)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
it 'should open the log file for appending' do
|
|
436
|
+
File.should_receive(:new).with(@log_location, 'a')
|
|
437
|
+
subject.setup_application
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it 'should set the log level' do
|
|
442
|
+
Chef::Config.stub(:[]).with(:log_location).and_return(nil)
|
|
443
|
+
Chef::Config.stub(:[]).with(:log_level).and_return(:info)
|
|
444
|
+
Chef::Log.should_receive(:level=).with(:info)
|
|
445
|
+
subject.setup_application
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
describe 'run_application' do
|
|
452
|
+
context 'with -d or --daemonize' do
|
|
453
|
+
before do
|
|
454
|
+
Chef::Config[:daemonize] = true
|
|
455
|
+
Kernel.stub :exec
|
|
456
|
+
Dir.stub :chdir
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
it 'should daemonize' do
|
|
460
|
+
Chef::Daemon.should_receive(:daemonize).with('chef-solr')
|
|
461
|
+
subject.run_application
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
it 'should change to the jetty home dir' do
|
|
466
|
+
Kernel.stub :exec
|
|
467
|
+
Dir.should_receive(:chdir).with(Chef::Config[:solr_jetty_path])
|
|
468
|
+
subject.run_application
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
context 'after changing to the jetty home dir' do
|
|
472
|
+
before do
|
|
473
|
+
Dir.should_receive(:chdir).and_yield
|
|
474
|
+
Chef::Daemon.stub :daemonize
|
|
475
|
+
Chef::Log.stub :info
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
it 'should start the process with the default settings' do
|
|
479
|
+
cmd = "java -Xmx#{Chef::Config[:solr_heap_size]} "
|
|
480
|
+
cmd << "-Xms#{Chef::Config[:solr_heap_size]} "
|
|
481
|
+
cmd << "-Dsolr.data.dir=#{Chef::Config[:solr_data_path]} "
|
|
482
|
+
cmd << "-Dsolr.solr.home=#{Chef::Config[:solr_home_path]} "
|
|
483
|
+
cmd << "-jar #{File.join(Chef::Config[:solr_jetty_path], 'start.jar')}"
|
|
484
|
+
|
|
485
|
+
Kernel.should_receive(:exec).with(cmd)
|
|
486
|
+
subject.run_application
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
it 'should log the command that solr is started with' do
|
|
490
|
+
cmd = /java.+solr.+jar.+start\.jar/
|
|
491
|
+
Chef::Log.should_receive(:info).with(cmd)
|
|
492
|
+
Kernel.stub :exec
|
|
493
|
+
subject.run_application
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
context 'with custom heap' do
|
|
497
|
+
it 'should start the process with the custom setting' do
|
|
498
|
+
Chef::Config[:solr_heap_size] = '2048M'
|
|
499
|
+
cmd_fragment = /-Xmx2048M -Xms2048M/
|
|
500
|
+
Kernel.should_receive(:exec).with(cmd_fragment)
|
|
501
|
+
subject.run_application
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
context 'with custom data path' do
|
|
506
|
+
it 'should start the process with the custom setting' do
|
|
507
|
+
Chef::Config[:solr_data_path] = '/opt/chef/solr_data'
|
|
508
|
+
cmd_fragment = /-Dsolr\.data\.dir=\/opt\/chef\/solr_data/
|
|
509
|
+
Kernel.should_receive(:exec).with(cmd_fragment)
|
|
510
|
+
subject.run_application
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
context 'with custom home path' do
|
|
515
|
+
it 'should start the process with the custom setting' do
|
|
516
|
+
Chef::Config[:solr_home_path] = '/opt/chef/solr/'
|
|
517
|
+
cmd_fragment = /-Dsolr\.solr\.home=\/opt\/chef\/solr/
|
|
518
|
+
Kernel.should_receive(:exec).with(cmd_fragment)
|
|
519
|
+
subject.run_application
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
context 'with custom jetty path' do
|
|
524
|
+
it 'should start the process with the custom setting' do
|
|
525
|
+
Chef::Config[:solr_jetty_path] = '/opt/chef/solr_jetty/'
|
|
526
|
+
cmd_fragment = /-jar \/opt\/chef\/solr_jetty\/start.jar/
|
|
527
|
+
Kernel.should_receive(:exec).with(cmd_fragment)
|
|
528
|
+
subject.run_application
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
context 'with custom java opts' do
|
|
533
|
+
it 'should start the java process with the custom setting' do
|
|
534
|
+
Chef::Config[:solr_java_opts] = '-XX:UseLargePages'
|
|
535
|
+
cmd_fragment = /-XX:UseLargePages/
|
|
536
|
+
Kernel.should_receive(:exec).with(cmd_fragment)
|
|
537
|
+
subject.run_application
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
context 'with -L or --logfile' do
|
|
542
|
+
it 'should close the previously opened log file and reopen it' do
|
|
543
|
+
Kernel.stub :exec
|
|
544
|
+
subject.logfile = StringIO.new
|
|
545
|
+
subject.should_receive(:close_and_reopen_log_file)
|
|
546
|
+
subject.run_application
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
describe 'close_and_reopen_log_file' do
|
|
555
|
+
it 'should close the log and reopen it' do
|
|
556
|
+
log = StringIO.new
|
|
557
|
+
Chef::Log.should_receive :close
|
|
558
|
+
STDOUT.should_receive(:reopen).with log
|
|
559
|
+
STDERR.should_receive(:reopen).with log
|
|
560
|
+
subject.logfile = log
|
|
561
|
+
subject.close_and_reopen_log_file
|
|
562
|
+
end
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
describe 'run' do
|
|
566
|
+
it { should respond_to :run}
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
end
|