beaker 0.0.0 → 1.0.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.
Files changed (98) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +8 -0
  3. data/README.md +6 -6
  4. data/beaker.gemspec +6 -2
  5. data/lib/beaker.rb +1 -1
  6. data/lib/beaker/answers.rb +34 -7
  7. data/lib/beaker/answers/version20.rb +124 -0
  8. data/lib/beaker/answers/version28.rb +21 -0
  9. data/lib/beaker/answers/version30.rb +24 -5
  10. data/lib/beaker/cli.rb +55 -41
  11. data/lib/beaker/command.rb +2 -2
  12. data/lib/beaker/dsl/helpers.rb +320 -106
  13. data/lib/beaker/dsl/install_utils.rb +202 -81
  14. data/lib/beaker/dsl/roles.rb +40 -0
  15. data/lib/beaker/host.rb +28 -20
  16. data/lib/beaker/host/unix.rb +7 -4
  17. data/lib/beaker/host/unix/pkg.rb +42 -12
  18. data/lib/beaker/host/windows.rb +9 -5
  19. data/lib/beaker/host/windows/group.rb +1 -1
  20. data/lib/beaker/host/windows/pkg.rb +41 -8
  21. data/lib/beaker/hypervisor.rb +23 -10
  22. data/lib/beaker/hypervisor/aixer.rb +15 -19
  23. data/lib/beaker/hypervisor/blimper.rb +71 -72
  24. data/lib/beaker/hypervisor/fusion.rb +11 -10
  25. data/lib/beaker/hypervisor/solaris.rb +17 -23
  26. data/lib/beaker/hypervisor/vagrant.rb +27 -12
  27. data/lib/beaker/hypervisor/vcloud.rb +154 -138
  28. data/lib/beaker/hypervisor/vcloud_pooled.rb +97 -0
  29. data/lib/beaker/hypervisor/vsphere.rb +8 -5
  30. data/lib/beaker/hypervisor/vsphere_helper.rb +43 -33
  31. data/lib/beaker/network_manager.rb +16 -12
  32. data/lib/beaker/options/command_line_parser.rb +199 -0
  33. data/lib/beaker/options/hosts_file_parser.rb +39 -0
  34. data/lib/beaker/options/options_file_parser.rb +45 -0
  35. data/lib/beaker/options/options_hash.rb +294 -0
  36. data/lib/beaker/options/parser.rb +288 -0
  37. data/lib/beaker/options/pe_version_scraper.rb +35 -0
  38. data/lib/beaker/options/presets.rb +70 -0
  39. data/lib/beaker/shared.rb +2 -1
  40. data/lib/beaker/shared/host_handler.rb +7 -2
  41. data/lib/beaker/shared/repetition.rb +1 -0
  42. data/lib/beaker/shared/timed.rb +14 -0
  43. data/lib/beaker/test_case.rb +2 -38
  44. data/lib/beaker/test_suite.rb +11 -25
  45. data/lib/beaker/utils/repo_control.rb +6 -8
  46. data/lib/beaker/utils/setup_helper.rb +9 -20
  47. data/spec/beaker/answers_spec.rb +109 -0
  48. data/spec/beaker/command_spec.rb +2 -2
  49. data/spec/beaker/dsl/assertions_spec.rb +1 -3
  50. data/spec/beaker/dsl/helpers_spec.rb +519 -84
  51. data/spec/beaker/dsl/install_utils_spec.rb +265 -16
  52. data/spec/beaker/dsl/roles_spec.rb +31 -10
  53. data/spec/beaker/host/windows/group_spec.rb +55 -0
  54. data/spec/beaker/host_spec.rb +130 -40
  55. data/spec/beaker/hypervisor/aixer_spec.rb +34 -0
  56. data/spec/beaker/hypervisor/blimper_spec.rb +77 -0
  57. data/spec/beaker/hypervisor/fusion_spec.rb +26 -0
  58. data/spec/beaker/hypervisor/hypervisor_spec.rb +66 -0
  59. data/spec/beaker/hypervisor/solaris_spec.rb +39 -0
  60. data/spec/beaker/hypervisor/vagrant_spec.rb +105 -0
  61. data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +60 -0
  62. data/spec/beaker/hypervisor/vcloud_spec.rb +70 -0
  63. data/spec/beaker/hypervisor/vsphere_helper_spec.rb +162 -0
  64. data/spec/beaker/hypervisor/vsphere_spec.rb +76 -0
  65. data/spec/beaker/options/command_line_parser_spec.rb +25 -0
  66. data/spec/beaker/options/data/LATEST +1 -0
  67. data/spec/beaker/options/data/badyaml.cfg +21 -0
  68. data/spec/beaker/options/data/hosts.cfg +21 -0
  69. data/spec/beaker/options/data/opts.txt +6 -0
  70. data/spec/beaker/options/hosts_file_parser_spec.rb +30 -0
  71. data/spec/beaker/options/options_file_parser_spec.rb +23 -0
  72. data/spec/beaker/options/options_hash_spec.rb +111 -0
  73. data/spec/beaker/options/parser_spec.rb +172 -0
  74. data/spec/beaker/options/pe_version_scaper_spec.rb +15 -0
  75. data/spec/beaker/options/presets_spec.rb +24 -0
  76. data/spec/beaker/puppet_command_spec.rb +54 -21
  77. data/spec/beaker/shared/error_handler_spec.rb +40 -0
  78. data/spec/beaker/shared/host_handler_spec.rb +104 -0
  79. data/spec/beaker/shared/repetition_spec.rb +72 -0
  80. data/spec/beaker/test_suite_spec.rb +3 -16
  81. data/spec/beaker/utils/ntp_control_spec.rb +42 -0
  82. data/spec/beaker/utils/repo_control_spec.rb +168 -0
  83. data/spec/beaker/utils/setup_helper_spec.rb +82 -0
  84. data/spec/beaker/utils/validator_spec.rb +58 -0
  85. data/spec/helpers.rb +97 -0
  86. data/spec/matchers.rb +39 -0
  87. data/spec/mock_blimpy.rb +48 -0
  88. data/spec/mock_fission.rb +60 -0
  89. data/spec/mock_vsphere.rb +310 -0
  90. data/spec/mock_vsphere_helper.rb +183 -0
  91. data/spec/mocks.rb +83 -0
  92. data/spec/spec_helper.rb +8 -1
  93. metadata +106 -13
  94. data/beaker.rb +0 -10
  95. data/lib/beaker/options_parsing.rb +0 -323
  96. data/lib/beaker/test_config.rb +0 -148
  97. data/spec/beaker/options_parsing_spec.rb +0 -37
  98. data/spec/mocks_and_helpers.rb +0 -34
@@ -129,106 +129,159 @@ module Beaker
129
129
  end
130
130
  end
131
131
 
132
- def do_install hosts, version, path, pre_30, options = {}
133
- #convenience methods for installation
134
- ########################################################
135
- def installer_cmd(host, version, installer)
136
- if host['platform'] =~ /windows/
137
- "cd #{host['working_dir']} && msiexec.exe /qn /i puppet-enterprise-#{version}.msi"
138
- else
139
- "cd #{host['working_dir']}/#{host['dist']} && ./#{installer}"
140
- end
132
+ #Create the PE install command string based upon the host and options settings
133
+ # @param [Host] host The host that PE is to be installed on
134
+ # @param [Hash{Symbol=>String}] options The options
135
+ # @option options [String] :installer The name of the installer to use for upgrading/installing
136
+ # @option options [String] :pe_ver_win Default PE version to install or upgrade to on Windows hosts
137
+ # (Othersie uses individual Windows hosts pe_ver)
138
+ # @option options [String :pe_ver Default PE version to install or upgrade to
139
+ # (Otherwise uses individual hosts pe_ver)
140
+ # @example
141
+ # on host, "#{installer_cmd(host, options)} -a #{host['working_dir']}/answers"
142
+ # @api private
143
+ def installer_cmd(host, options)
144
+ if host['platform'] =~ /windows/
145
+ version = options[:pe_ver_win] || host['pe_ver']
146
+ "cd #{host['working_dir']} && msiexec.exe /qn /i puppet-enterprise-#{version}.msi"
147
+ else
148
+ version = options[:pe_ver] || host['pe_ver']
149
+ "cd #{host['working_dir']}/#{host['dist']} && ./#{options[:installer]}"
141
150
  end
142
- def link_exists?(link)
143
- require "net/http"
144
- require "open-uri"
145
- url = URI.parse(link)
146
- Net::HTTP.start(url.host, url.port) do |http|
147
- return http.head(url.request_uri).code == "200"
148
- end
151
+ end
152
+
153
+ #Determine is a given URL is accessible
154
+ #@param [String] link The URL to examine
155
+ #@return [Boolean] true if the URL has a '200' HTTP response code, false otherwise
156
+ #@example
157
+ # extension = link_exists?("#{URL}.tar.gz") ? ".tar.gz" : ".tar"
158
+ # @api private
159
+ def link_exists?(link)
160
+ require "net/http"
161
+ require "open-uri"
162
+ url = URI.parse(link)
163
+ Net::HTTP.start(url.host, url.port) do |http|
164
+ return http.head(url.request_uri).code == "200"
149
165
  end
150
- def fetch_puppet(hosts, version, path)
166
+ end
167
+
168
+ #Determine the PE package to download/upload per-host, download/upload that package onto the host
169
+ #and unpack it.
170
+ # @param [Array<Host>] hosts The hosts to download/upload and unpack PE onto
171
+ # @param [Hash{Symbol=>Symbol, String}] options The options
172
+ # @option options [String] :pe_dir Default directory or URL to pull PE package from
173
+ # (Otherwise uses individual hosts pe_dir)
174
+ # @option options [String] :pe_ver Default PE version to install or upgrade to
175
+ # (Otherwise uses individual hosts pe_ver)
176
+ # @option options [String] :pe_ver_win Default PE version to install or upgrade to on Windows hosts
177
+ # (Otherwise uses individual Windows hosts pe_ver)
178
+ # @api private
179
+ def fetch_puppet(hosts, options)
180
+ hosts.each do |host|
181
+ windows = host['platform'] =~ /windows/
182
+ path = options[:pe_dir] || host['pe_dir']
151
183
  local = File.directory?(path)
152
- hosts.each do |host|
153
- filename = ""
184
+ filename = ""
185
+ extension = ""
186
+ if windows
187
+ version = options[:pe_ver_win] || host['pe_ver']
188
+ filename = "puppet-enterprise-#{version}"
189
+ extension = ".msi"
190
+ else
191
+ filename = "#{host['dist']}"
154
192
  extension = ""
155
- if host['platform'] =~ /windows/
156
- filename = "puppet-enterprise-#{version}"
157
- extension = ".msi"
158
- else
159
- filename = "#{host['dist']}"
160
- extension = ""
161
- if local
162
- extension = File.exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
163
- else
164
- extension = link_exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
165
- end
166
- end
167
193
  if local
168
- if not File.exists?("#{path}/#{filename}#{extension}")
169
- raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
170
- end
171
- scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
194
+ extension = File.exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
172
195
  else
173
- if not link_exists?("#{path}/#{filename}#{extension}")
174
- raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
175
- end
176
- on host, "cd #{host['working_dir']}; curl #{path}/#{filename}#{extension} -o #{filename}#{extension}"
177
- end
178
- if extension =~ /gz/
179
- on host, "cd #{host['working_dir']}; gunzip #{filename}#{extension}"
180
- end
181
- if extension =~ /tar/
182
- on host, "cd #{host['working_dir']}; tar -xvf #{filename}.tar"
196
+ extension = link_exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
183
197
  end
184
198
  end
199
+ if local
200
+ if not File.exists?("#{path}/#{filename}#{extension}")
201
+ raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
202
+ end
203
+ scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
204
+ else
205
+ if not link_exists?("#{path}/#{filename}#{extension}")
206
+ raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
207
+ end
208
+ on host, "cd #{host['working_dir']}; curl #{path}/#{filename}#{extension} -o #{filename}#{extension}"
209
+ end
210
+ if extension =~ /gz/
211
+ on host, "cd #{host['working_dir']}; gunzip #{filename}#{extension}"
212
+ end
213
+ if extension =~ /tar/
214
+ on host, "cd #{host['working_dir']}; tar -xvf #{filename}.tar"
215
+ end
185
216
  end
186
- ########################################################
187
- #start installation steps here
188
- options[:installer] = 'puppet-enterprise-installer' unless options[:installer]
189
- options[:type] = :install unless options[:type]
217
+ end
218
+
219
+ #Perform a Puppet Enterprise upgrade or install
220
+ # @param [Array<Host>] hosts The hosts to install or upgrade PE on
221
+ # @param [Hash{Symbol=>Symbol, String}] options The options
222
+ # @option options [String] :pe_dir Default directory or URL to pull PE package from
223
+ # (Otherwise uses individual hosts pe_dir)
224
+ # @option options [String] :pe_ver Default PE version to install or upgrade to
225
+ # (Otherwise uses individual hosts pe_ver)
226
+ # @option options [String] :pe_ver_win Default PE version to install or upgrade to on Windows hosts
227
+ # (Otherwise uses individual Windows hosts pe_ver)
228
+ # @option options [String] :installer ('puppet-enterprise-installer') The name of the installer to use for upgrading/installing
229
+ # @option options [Symbol] :type (:install) One of :upgrade or :install
230
+ #
231
+ #
232
+ # @example
233
+ # do_install(hosts, {:type => :upgrade, :pe_dir => path, :pe_ver => version, :pe_ver_win => version_win})
234
+ #
235
+ # @api private
236
+ #
237
+ def do_install hosts, options = {}
238
+ options[:installer] = options[:installer] || 'puppet-enterprise-installer'
239
+ options[:type] = options[:type] || :install
190
240
  hostcert='uname | grep -i sunos > /dev/null && hostname || hostname -s'
191
241
  master_certname = on(master, hostcert).stdout.strip
192
- answers = Beaker::Answers.answers(version, hosts, master_certname, options)
193
- special_nodes = [master, database, dashboard].uniq
194
- real_agents = agents - special_nodes
242
+ pre30database = version_is_less(options[:pe_ver] || database['pe_ver'], '3.0')
243
+ pre30master = version_is_less(options[:pe_ver] || master['pe_ver'], '3.0')
195
244
 
196
245
  # Set PE distribution for all the hosts, create working dir
197
246
  use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
198
247
  hosts.each do |host|
199
- platform = use_all_tar ? 'all' : host['platform']
200
- host['dist'] = "puppet-enterprise-#{version}-#{platform}"
248
+ if host['platform'] !~ /windows/
249
+ platform = use_all_tar ? 'all' : host['platform']
250
+ version = options[:pe_ver] || host['pe_ver']
251
+ host['dist'] = "puppet-enterprise-#{version}-#{platform}"
252
+ end
201
253
  host['working_dir'] = "/tmp/" + Time.new.strftime("%Y-%m-%d_%H.%M.%S") #unique working dirs make me happy
202
254
  on host, "mkdir #{host['working_dir']}"
203
255
  end
204
256
 
205
- fetch_puppet(hosts, version, path)
257
+ fetch_puppet(hosts, options)
206
258
 
207
259
  hosts.each do |host|
208
260
  # Database host was added in 3.0. Skip it if installing an older version
209
- next if host == database and host != master and host != dashboard and pre_30
261
+ next if host == database and host != master and host != dashboard and pre30database
210
262
  if host['platform'] =~ /windows/
211
- on host, "#{installer_cmd(host, version, options[:installer])} PUPPET_MASTER_SERVER=#{master} PUPPET_AGENT_CERTNAME=#{host}"
263
+ on host, "#{installer_cmd(host, options)} PUPPET_MASTER_SERVER=#{master} PUPPET_AGENT_CERTNAME=#{host}"
212
264
  else
265
+ answers = Beaker::Answers.answers(options[:pe_ver] || host['pe_ver'], hosts, master_certname, options)
213
266
  create_remote_file host, "#{host['working_dir']}/answers", Beaker::Answers.answer_string(host, answers)
214
267
 
215
- on host, "#{installer_cmd(host, version, options[:installer])} -a #{host['working_dir']}/answers"
268
+ on host, "#{installer_cmd(host, options)} -a #{host['working_dir']}/answers"
216
269
  end
217
270
  end
218
271
 
219
272
 
220
- # If we're installing a version less than 3.0, ignore the database host
273
+ # If we're installing a database version less than 3.0, ignore the database host
221
274
  install_hosts = hosts.dup
222
- install_hosts.delete(database) if pre_30 and database != master and database != dashboard
275
+ install_hosts.delete(database) if pre30database and database != master and database != dashboard
223
276
 
224
277
  # On each agent, we ensure the certificate is signed then shut down the agent
225
278
  install_hosts.each do |host|
226
- sign_certificate(host)
227
- stop_agent(host)
279
+ sign_certificate_for(host)
280
+ stop_agent_on(host)
228
281
  end
229
282
 
230
- # Wait for PuppetDB to be totally up and running
231
- sleep_until_puppetdb_started(database) unless pre_30
283
+ # Wait for PuppetDB to be totally up and running (post 3.0 version of pe only)
284
+ sleep_until_puppetdb_started(database) unless pre30database
232
285
 
233
286
  # Run the agent once to ensure everything is in the dashboard
234
287
  install_hosts.each do |host|
@@ -239,7 +292,7 @@ module Beaker
239
292
  # and would cause puppetdb to be bounced by the agent run. By sleeping
240
293
  # again here, we ensure that if that bounce happens during an upgrade
241
294
  # test we won't fail early in the install process.
242
- if version == '3.0.0' and host == database
295
+ if host['pe_ver'] == '3.0.0' and host == database
243
296
  sleep_until_puppetdb_started(database)
244
297
  end
245
298
  end
@@ -248,7 +301,7 @@ module Beaker
248
301
  wait_for_host_in_dashboard(host)
249
302
  end
250
303
 
251
- if pre_30
304
+ if pre30master
252
305
  task = 'nodegroup:add_all_nodes group=default'
253
306
  else
254
307
  task = 'defaultgroup:ensure_default_group'
@@ -260,37 +313,105 @@ module Beaker
260
313
  on install_hosts, puppet_agent('-t'), :acceptable_exit_codes => [0,2]
261
314
  end
262
315
 
263
- #is version a < version b
264
- #3.0.0-160-gac44cfb is greater than 3.0.0, and 2.8.2
316
+ #Is PE version a less than PE version b
317
+ #@param [String] a A PE version of the from '\d.\d.\d.*'
318
+ #@param [String] b A PE version of the form '\d.\d.\d.*'
319
+ #@return [Boolean] true if a is less than b, otherwise return false
320
+ #
321
+ #@note 3.0.0-160-gac44cfb is greater than 3.0.0, and 2.8.2
322
+ # @!visibility private
265
323
  def version_is_less a, b
266
- a = a.split('-')[0].split('.')
267
- b = b.split('-')[0].split('.')
268
- (0...a.length).each do |i|
269
- if i < b.length
270
- if a[i] < b[i]
324
+ a_nums = a.split('-')[0].split('.')
325
+ b_nums = b.split('-')[0].split('.')
326
+ (0...a_nums.length).each do |i|
327
+ if i < b_nums.length
328
+ if a_nums[i] < b_nums[i]
271
329
  return true
272
- elsif a[i] > b[i]
330
+ elsif a_nums[i] > b_nums[i]
273
331
  return false
274
332
  end
275
333
  else
276
334
  return false
277
335
  end
278
336
  end
337
+ #checks all dots, they are equal so examine the rest
338
+ a_rest = a.split('-', 2)[1]
339
+ b_rest = b.split('-', 2)[1]
340
+ if a_rest and b_rest and a_rest < b_rest
341
+ return false
342
+ elsif a_rest and not b_rest
343
+ return false
344
+ elsif not a_rest and b_rest
345
+ return true
346
+ end
279
347
  return false
280
348
  end
281
349
 
282
- def install_pe version, path
283
- pre_30 = version_is_less(version, '3.0')
284
- step "Install #{version} PE on #{path}"
285
- do_install hosts, version, path, pre_30
350
+ #Sort array of hosts so that it has the correct order for PE installation based upon each host's role
351
+ # @example
352
+ # h = sorted_hosts
353
+ #
354
+ # @note Order for installation should be
355
+ # First : master
356
+ # Second: database host (if not same as master)
357
+ # Third: dashboard (if not same as master or database)
358
+ # Fourth: everything else
359
+ #
360
+ # @!visibility private
361
+ def sorted_hosts
362
+ special_nodes = [master, database, dashboard].uniq
363
+ real_agents = agents - special_nodes
364
+ special_nodes + real_agents
286
365
  end
287
366
 
288
- def upgrade_pe version, path, from
367
+ #Install PE based upon host configuration and options
368
+ # @example
369
+ # install_pe
370
+ #
371
+ # @note Either pe_ver and pe_dir should be set in the ENV or each host should have pe_ver and pe_dir set individually.
372
+ # Install file names are assumed to be of the format puppet-enterprise-VERSION-PLATFORM.(tar)|(tar.gz)
373
+ # for Unix like systems and puppet-enterprise-VERSION.msi for Windows systems.
374
+ #
375
+ # @api dsl
376
+ def install_pe
377
+ #process the version files if necessary
378
+ hosts.each do |host|
379
+ if host['platform'] =~ /windows/
380
+ host['pe_ver'] = host['pe_ver'] ||
381
+ Beaker::Options::PEVersionScraper.load_pe_version(host[:pe_dir] || options[:pe_dir], options[:pe_version_file_win])
382
+ else
383
+ host['pe_ver'] = host['pe_ver'] ||
384
+ Beaker::Options::PEVersionScraper.load_pe_version(host[:pe_dir] || options[:pe_dir], options[:pe_version_file])
385
+ end
386
+ end
387
+ do_install sorted_hosts
388
+ end
389
+
390
+ #Upgrade PE based upon host configuration and options
391
+ # @param [String] path A path (either local directory or a URL to a listing of PE builds).
392
+ # Will contain a LATEST file indicating the latest build to install.
393
+ # @example
394
+ # upgrade_pe("http://neptune.puppetlabs.lan/3.0/ci-ready/")
395
+ #
396
+ # @note Install file names are assumed to be of the format puppet-enterprise-VERSION-PLATFORM.(tar)|(tar.gz)
397
+ # for Unix like systems and puppet-enterprise-VERSION.msi for Windows systems.
398
+ # @api dsl
399
+ def upgrade_pe path
400
+ version = Options::PEVersionScraper.load_pe_version(path, options[:pe_version_file])
401
+ version_win = Options::PEVersionScraper.load_pe_version(path, options[:pe_version_file_win])
289
402
  pre_30 = version_is_less(version, '3.0')
290
403
  if pre_30
291
- do_install(hosts, version, path, pre_30, :type => :upgrade, :installer => 'puppet-enterprise-upgrader', :from => from)
404
+ do_install(sorted_hosts, {:type => :upgrade, :pe_dir => path, :pe_ver => version, :pe_ver_win => version_win, :installer => 'puppet-enterprise-upgrader'})
292
405
  else
293
- do_install(hosts, version, path, pre_30, :type => :upgrade, :from => from)
406
+ do_install(sorted_hosts, {:type => :upgrade, :pe_dir => path, :pe_ver => version, :pe_ver_win => version_win})
407
+ end
408
+ #at this point we've completed a successful upgrade, update the host pe_ver to reflect that
409
+ hosts.each do |host|
410
+ if host['platform'] =~ /windows/
411
+ host['pe_ver'] = version_win
412
+ else
413
+ host['pe_ver'] = version
414
+ end
294
415
  end
295
416
  end
296
417
 
@@ -68,6 +68,44 @@ module Beaker
68
68
  find_only_one :dashboard
69
69
  end
70
70
 
71
+ # The default host
72
+ # - if only one host defined, then that host
73
+ # OR
74
+ # - host with 'default' as a role
75
+ # OR
76
+ # - host with 'master' as a role
77
+ #
78
+ # @return [Array<Host>]
79
+ # @raise [Beaker::DSL::Outcomes::FailTest] if no default host is found
80
+ #
81
+ # @example Basic usage
82
+ # on, default, "curl https://#{database}/nodes/#{agent}"
83
+ #
84
+ def default
85
+ if hosts.length == 1
86
+ return hosts[0]
87
+ elsif any_hosts_as? :default
88
+ return find_only_one :default
89
+ elsif any_hosts_as? :master
90
+ return find_only_one :master
91
+ else
92
+ raise DSL::Outcomes::FailTest, "no default host specified"
93
+ end
94
+ end
95
+
96
+ # Determine if there is a host or hosts with the given role defined
97
+ # @return [Boolean] True if there is a host with role, false otherwise
98
+ #
99
+ # @example Usage
100
+ # if any_hosts_as?(:master)
101
+ # puts "master is defined"
102
+ # end
103
+ #
104
+ # @api public
105
+ def any_hosts_as?(role)
106
+ hosts_as(role).length > 0
107
+ end
108
+
71
109
  # Select hosts that include a desired role from #hosts
72
110
  #
73
111
  # @param [String, Symbol] desired_role The role to select for
@@ -91,6 +129,8 @@ module Beaker
91
129
  # the specified role is NOT found.
92
130
  def find_only_one role
93
131
  only_host_with_role(hosts, role)
132
+ rescue ArgumentError => e
133
+ raise DSL::Outcomes::FailTest, e.to_s
94
134
  end
95
135
  end
96
136
  end
data/lib/beaker/host.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'socket'
2
- require 'timeout'
3
2
 
4
3
  %w(command ssh_connection).each do |lib|
5
4
  begin
@@ -11,6 +10,7 @@ end
11
10
 
12
11
  module Beaker
13
12
  class Host
13
+ SELECT_TIMEOUT = 30
14
14
 
15
15
  # This class providers array syntax for using puppet --configprint on a host
16
16
  class PuppetConfigReader
@@ -25,34 +25,34 @@ module Beaker
25
25
  end
26
26
  end
27
27
 
28
- def self.create name, options, config
29
- case config['HOSTS'][name]['platform']
28
+ def self.create name, options
29
+ case options['HOSTS'][name]['platform']
30
30
  when /windows/
31
- Windows::Host.new name, options, config
31
+ Windows::Host.new name, options
32
32
  when /aix/
33
- Aix::Host.new name, options, config
33
+ Aix::Host.new name, options
34
34
  else
35
- Unix::Host.new name, options, config
35
+ Unix::Host.new name, options
36
36
  end
37
37
  end
38
38
 
39
39
  attr_accessor :logger
40
40
  attr_reader :name, :defaults
41
- def initialize name, options, config
41
+ def initialize name, options
42
42
  @logger = options[:logger]
43
- @name, @options, @config = name, options.dup, config
43
+ @name, @options = name.to_s, options.dup
44
44
 
45
45
  # This is annoying and its because of drift/lack of enforcement/lack of having
46
46
  # a explict relationship between our defaults, our setup steps and how they're
47
47
  # related through 'type' and the differences between the assumption of our two
48
48
  # configurations we have for many of our products
49
49
  type = is_pe? ? :pe : :foss
50
- @defaults = merge_defaults_for_type @config, type
50
+ @defaults = merge_defaults_for_type @options, type
51
51
  end
52
52
 
53
- def merge_defaults_for_type config, type
53
+ def merge_defaults_for_type options, type
54
54
  defaults = self.class.send "#{type}_defaults".to_sym
55
- defaults.merge(config['CONFIG']).merge(config['HOSTS'][name])
55
+ defaults.merge(options.merge((options['HOSTS'][name])))
56
56
  end
57
57
 
58
58
  def node_name
@@ -63,18 +63,26 @@ module Beaker
63
63
  end
64
64
 
65
65
  def port_open? port
66
- Timeout.timeout 1 do
67
- begin
68
- TCPSocket.new(reachable_name, port).close
69
- return true
70
- rescue Errno::ECONNREFUSED
71
- return false
66
+ s = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
67
+ sa = Socket.sockaddr_in(port, reachable_name)
68
+
69
+ begin
70
+ s.connect_nonblock(sa)
71
+ rescue Errno::EINPROGRESS
72
+ if IO.select(nil, [s], nil, SELECT_TIMEOUT)
73
+ begin
74
+ s.connect_nonblock(sa)
75
+ rescue Errno::EISCONN
76
+ return true
77
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
78
+ return false
79
+ end
72
80
  end
73
81
  end
82
+ return false
74
83
  end
75
84
 
76
85
  def up?
77
- require 'socket'
78
86
  begin
79
87
  Socket.getaddrinfo( reachable_name, nil )
80
88
  return true
@@ -120,7 +128,7 @@ module Beaker
120
128
  end
121
129
 
122
130
  def is_pe?
123
- @config.is_pe?
131
+ @options.is_pe?
124
132
  end
125
133
 
126
134
  def connection
@@ -161,7 +169,7 @@ module Beaker
161
169
  # No, TestCase has the knowledge about whether its failed, checking acceptable
162
170
  # exit codes at the host level and then raising...
163
171
  # is it necessary to break execution??
164
- unless result.exit_code_in?(options[:acceptable_exit_codes] || [0])
172
+ unless result.exit_code_in?(Array(options[:acceptable_exit_codes] || 0))
165
173
  limit = 10
166
174
  raise "Host '#{self}' exited with #{result.exit_code} running:\n #{cmdline}\nLast #{limit} lines of output were:\n#{result.formatted_output(limit)}"
167
175
  end