beaker 2.7.1 → 2.8.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 (53) hide show
  1. checksums.yaml +8 -8
  2. data/HISTORY.md +121 -2
  3. data/lib/beaker/dsl.rb +2 -2
  4. data/lib/beaker/dsl/helpers.rb +13 -1429
  5. data/lib/beaker/dsl/helpers/facter_helpers.rb +48 -0
  6. data/lib/beaker/dsl/helpers/hiera_helpers.rb +71 -0
  7. data/lib/beaker/dsl/helpers/host_helpers.rb +506 -0
  8. data/lib/beaker/dsl/helpers/puppet_helpers.rb +698 -0
  9. data/lib/beaker/dsl/helpers/tk_helpers.rb +101 -0
  10. data/lib/beaker/dsl/helpers/web_helpers.rb +115 -0
  11. data/lib/beaker/dsl/install_utils.rb +8 -1570
  12. data/lib/beaker/dsl/install_utils/ezbake_utils.rb +256 -0
  13. data/lib/beaker/dsl/install_utils/module_utils.rb +237 -0
  14. data/lib/beaker/dsl/install_utils/pe_utils.rb +518 -0
  15. data/lib/beaker/dsl/install_utils/puppet_utils.rb +722 -0
  16. data/lib/beaker/dsl/outcomes.rb +0 -4
  17. data/lib/beaker/dsl/roles.rb +0 -3
  18. data/lib/beaker/dsl/structure.rb +127 -4
  19. data/lib/beaker/dsl/wrappers.rb +0 -4
  20. data/lib/beaker/host.rb +23 -0
  21. data/lib/beaker/host/unix/pkg.rb +4 -4
  22. data/lib/beaker/host_prebuilt_steps.rb +11 -5
  23. data/lib/beaker/hypervisor/vagrant.rb +1 -0
  24. data/lib/beaker/hypervisor/vmpooler.rb +38 -0
  25. data/lib/beaker/logger.rb +10 -4
  26. data/lib/beaker/network_manager.rb +5 -4
  27. data/lib/beaker/options/command_line_parser.rb +7 -0
  28. data/lib/beaker/shared.rb +2 -1
  29. data/lib/beaker/shared/semvar.rb +41 -0
  30. data/lib/beaker/test_suite.rb +20 -6
  31. data/lib/beaker/version.rb +1 -1
  32. data/spec/beaker/dsl/helpers/facter_helpers_spec.rb +59 -0
  33. data/spec/beaker/dsl/helpers/hiera_helpers_spec.rb +96 -0
  34. data/spec/beaker/dsl/helpers/host_helpers_spec.rb +413 -0
  35. data/spec/beaker/dsl/{helpers_spec.rb → helpers/puppet_helpers_spec.rb} +2 -611
  36. data/spec/beaker/dsl/helpers/tk_helpers_spec.rb +83 -0
  37. data/spec/beaker/dsl/helpers/web_helpers_spec.rb +60 -0
  38. data/spec/beaker/dsl/install_utils/module_utils_spec.rb +241 -0
  39. data/spec/beaker/dsl/install_utils/pe_utils_spec.rb +475 -0
  40. data/spec/beaker/dsl/install_utils/puppet_utils_spec.rb +523 -0
  41. data/spec/beaker/dsl/structure_spec.rb +108 -0
  42. data/spec/beaker/host_prebuilt_steps_spec.rb +44 -0
  43. data/spec/beaker/host_spec.rb +41 -0
  44. data/spec/beaker/hypervisor/vagrant_spec.rb +2 -1
  45. data/spec/beaker/logger_spec.rb +9 -2
  46. data/spec/beaker/network_manager_spec.rb +7 -1
  47. data/spec/beaker/options/command_line_parser_spec.rb +3 -2
  48. data/spec/beaker/shared/semvar_spec.rb +36 -0
  49. data/spec/beaker/test_suite_spec.rb +48 -0
  50. data/spec/mocks.rb +10 -0
  51. metadata +23 -5
  52. data/lib/beaker/dsl/ezbake_utils.rb +0 -259
  53. data/spec/beaker/dsl/install_utils_spec.rb +0 -1242
@@ -0,0 +1,518 @@
1
+ module Beaker
2
+ module DSL
3
+ module InstallUtils
4
+ #
5
+ # This module contains methods to help installing/upgrading PE builds - including Higgs installs
6
+ #
7
+ # To mix this is into a class you need the following:
8
+ # * a method *hosts* that yields any hosts implementing
9
+ # {Beaker::Host}'s interface to act upon.
10
+ # * a method *options* that provides an options hash, see {Beaker::Options::OptionsHash}
11
+ # * the module {Beaker::DSL::Roles} that provides access to the various hosts implementing
12
+ # {Beaker::Host}'s interface to act upon
13
+ # * the module {Beaker::DSL::Wrappers} the provides convenience methods for {Beaker::DSL::Command} creation
14
+ module PEUtils
15
+
16
+ #Sort array of hosts so that it has the correct order for PE installation based upon each host's role
17
+ # @example
18
+ # h = sorted_hosts
19
+ #
20
+ # @note Order for installation should be
21
+ # First : master
22
+ # Second: database host (if not same as master)
23
+ # Third: dashboard (if not same as master or database)
24
+ # Fourth: everything else
25
+ #
26
+ # @!visibility private
27
+ def sorted_hosts
28
+ special_nodes = []
29
+ [master, database, dashboard].uniq.each do |host|
30
+ special_nodes << host if host != nil
31
+ end
32
+ real_agents = agents - special_nodes
33
+ special_nodes + real_agents
34
+ end
35
+
36
+ #Create the PE install command string based upon the host and options settings
37
+ # @param [Host] host The host that PE is to be installed on
38
+ # For UNIX machines using the full PE installer, the host object must have the 'pe_installer' field set correctly.
39
+ # @param [Hash{Symbol=>String}] opts The options
40
+ # @option opts [String] :pe_ver_win Default PE version to install or upgrade to on Windows hosts
41
+ # (Othersie uses individual Windows hosts pe_ver)
42
+ # @option opts [String] :pe_ver Default PE version to install or upgrade to
43
+ # (Otherwise uses individual hosts pe_ver)
44
+ # @option opts [Boolean] :pe_debug (false) Should we run the installer in debug mode?
45
+ # @example
46
+ # on host, "#{installer_cmd(host, opts)} -a #{host['working_dir']}/answers"
47
+ # @api private
48
+ def installer_cmd(host, opts)
49
+ version = host['pe_ver'] || opts[:pe_ver]
50
+ if host['platform'] =~ /windows/
51
+ log_file = "#{File.basename(host['working_dir'])}.log"
52
+ pe_debug = host[:pe_debug] || opts[:pe_debug] ? " && cat #{log_file}" : ''
53
+ if host.is_cygwin?
54
+ "cd #{host['working_dir']} && cmd /C 'start /w msiexec.exe /qn /L*V #{log_file} /i #{host['dist']}.msi PUPPET_MASTER_SERVER=#{master} PUPPET_AGENT_CERTNAME=#{host}'#{pe_debug}"
55
+ else
56
+ "cd #{host['working_dir']} && msiexec.exe /qn /L*V #{log_file} /i #{host['dist']}.msi PUPPET_MASTER_SERVER=#{master} PUPPET_AGENT_CERTNAME=#{host}#{pe_debug}"
57
+ end
58
+ # Frictionless install didn't exist pre-3.2.0, so in that case we fall
59
+ # through and do a regular install.
60
+ elsif host['roles'].include? 'frictionless' and ! version_is_less(version, '3.2.0')
61
+ # PE 3.4 introduced the ability to pass in config options to the bash script in the form
62
+ # of <section>:<key>=<value>
63
+ frictionless_install_opts = []
64
+ if host.has_key?('frictionless_options') and ! version_is_less(version, '3.4.0')
65
+ # since we have options to pass in, we need to tell the bash script
66
+ host['frictionless_options'].each do |section, settings|
67
+ settings.each do |key, value|
68
+ frictionless_install_opts << "#{section}:#{key}=#{value}"
69
+ end
70
+ end
71
+ end
72
+
73
+ pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -x' : ''
74
+ "cd #{host['working_dir']} && curl --tlsv1 -kO https://#{master}:8140/packages/#{version}/install.bash && bash#{pe_debug} install.bash #{frictionless_install_opts.join(' ')}".strip
75
+ elsif host['platform'] =~ /osx/
76
+ version = host['pe_ver'] || opts[:pe_ver]
77
+ pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -verboseR' : ''
78
+ "cd #{host['working_dir']} && hdiutil attach #{host['dist']}.dmg && installer#{pe_debug} -pkg /Volumes/puppet-enterprise-#{version}/puppet-enterprise-installer-#{version}.pkg -target /"
79
+ elsif host['platform'] =~ /eos/
80
+ commands = ['enable', "extension puppet-enterprise-#{version}-#{host['platform']}.swix"]
81
+ command = commands.join("\n")
82
+ "Cli -c '#{command}'"
83
+ else
84
+ pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -D' : ''
85
+ "cd #{host['working_dir']}/#{host['dist']} && ./#{host['pe_installer']}#{pe_debug} -a #{host['working_dir']}/answers"
86
+ end
87
+ end
88
+
89
+ #Determine the PE package to download/upload on a mac host, download/upload that package onto the host.
90
+ # Assumed file name format: puppet-enterprise-3.3.0-rc1-559-g97f0833-osx-10.9-x86_64.dmg.
91
+ # @param [Host] host The mac host to download/upload and unpack PE onto
92
+ # @param [Hash{Symbol=>Symbol, String}] opts The options
93
+ # @option opts [String] :pe_dir Default directory or URL to pull PE package from
94
+ # (Otherwise uses individual hosts pe_dir)
95
+ # @api private
96
+ def fetch_pe_on_mac(host, opts)
97
+ path = host['pe_dir'] || opts[:pe_dir]
98
+ local = File.directory?(path)
99
+ filename = "#{host['dist']}"
100
+ extension = ".dmg"
101
+ if local
102
+ if not File.exists?("#{path}/#{filename}#{extension}")
103
+ raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
104
+ end
105
+ scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
106
+ else
107
+ if not link_exists?("#{path}/#{filename}#{extension}")
108
+ raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
109
+ end
110
+ on host, "cd #{host['working_dir']}; curl -O #{path}/#{filename}#{extension}"
111
+ end
112
+ end
113
+
114
+ #Determine the PE package to download/upload on a windows host, download/upload that package onto the host.
115
+ #Assumed file name format: puppet-enterprise-3.3.0-rc1-559-g97f0833.msi
116
+ # @param [Host] host The windows host to download/upload and unpack PE onto
117
+ # @param [Hash{Symbol=>Symbol, String}] opts The options
118
+ # @option opts [String] :pe_dir Default directory or URL to pull PE package from
119
+ # (Otherwise uses individual hosts pe_dir)
120
+ # @option opts [String] :pe_ver_win Default PE version to install or upgrade to
121
+ # (Otherwise uses individual hosts pe_ver)
122
+ # @api private
123
+ def fetch_pe_on_windows(host, opts)
124
+ path = host['pe_dir'] || opts[:pe_dir]
125
+ local = File.directory?(path)
126
+ version = host['pe_ver'] || opts[:pe_ver_win]
127
+ filename = "#{host['dist']}"
128
+ extension = ".msi"
129
+ if local
130
+ if not File.exists?("#{path}/#{filename}#{extension}")
131
+ raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
132
+ end
133
+ scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
134
+ else
135
+ if not link_exists?("#{path}/#{filename}#{extension}")
136
+ raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
137
+ end
138
+ if host.is_cygwin?
139
+ on host, "cd #{host['working_dir']}; curl -O #{path}/#{filename}#{extension}"
140
+ else
141
+ on host, powershell("$webclient = New-Object System.Net.WebClient; $webclient.DownloadFile('#{path}/#{filename}#{extension}','#{host['wor
142
+ king_dir']}\\#{filename}#{extension}')")
143
+ end
144
+ end
145
+ end
146
+
147
+ #Determine the PE package to download/upload on a unix style host, download/upload that package onto the host
148
+ #and unpack it.
149
+ # @param [Host] host The unix style host to download/upload and unpack PE onto
150
+ # @param [Hash{Symbol=>Symbol, String}] opts The options
151
+ # @option opts [String] :pe_dir Default directory or URL to pull PE package from
152
+ # (Otherwise uses individual hosts pe_dir)
153
+ # @api private
154
+ def fetch_pe_on_unix(host, opts)
155
+ path = host['pe_dir'] || opts[:pe_dir]
156
+ local = File.directory?(path)
157
+ filename = "#{host['dist']}"
158
+ if local
159
+ extension = File.exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
160
+ if not File.exists?("#{path}/#{filename}#{extension}")
161
+ raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
162
+ end
163
+ scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
164
+ if extension =~ /gz/
165
+ on host, "cd #{host['working_dir']}; gunzip #{filename}#{extension}"
166
+ end
167
+ if extension =~ /tar/
168
+ on host, "cd #{host['working_dir']}; tar -xvf #{filename}.tar"
169
+ end
170
+ else
171
+ if host['platform'] =~ /eos/
172
+ extension = '.swix'
173
+ else
174
+ extension = link_exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
175
+ end
176
+ if not link_exists?("#{path}/#{filename}#{extension}")
177
+ raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
178
+ end
179
+
180
+ if host['platform'] =~ /eos/
181
+ commands = ['enable', "copy #{path}/#{filename}#{extension} extension:"]
182
+ command = commands.join("\n")
183
+ on host, "Cli -c '#{command}'"
184
+ else
185
+ unpack = 'tar -xvf -'
186
+ unpack = extension =~ /gz/ ? 'gunzip | ' + unpack : unpack
187
+ on host, "cd #{host['working_dir']}; curl #{path}/#{filename}#{extension} | #{unpack}"
188
+ end
189
+ end
190
+ end
191
+
192
+ #Determine the PE package to download/upload per-host, download/upload that package onto the host
193
+ #and unpack it.
194
+ # @param [Array<Host>] hosts The hosts to download/upload and unpack PE onto
195
+ # @param [Hash{Symbol=>Symbol, String}] opts The options
196
+ # @option opts [String] :pe_dir Default directory or URL to pull PE package from
197
+ # (Otherwise uses individual hosts pe_dir)
198
+ # @option opts [String] :pe_ver Default PE version to install or upgrade to
199
+ # (Otherwise uses individual hosts pe_ver)
200
+ # @option opts [String] :pe_ver_win Default PE version to install or upgrade to on Windows hosts
201
+ # (Otherwise uses individual Windows hosts pe_ver)
202
+ # @api private
203
+ def fetch_pe(hosts, opts)
204
+ hosts.each do |host|
205
+ # We install Puppet from the master for frictionless installs, so we don't need to *fetch* anything
206
+ next if host['roles'].include?('frictionless') && (! version_is_less(opts[:pe_ver] || host['pe_ver'], '3.2.0'))
207
+
208
+ if host['platform'] =~ /windows/
209
+ fetch_pe_on_windows(host, opts)
210
+ elsif host['platform'] =~ /osx/
211
+ fetch_pe_on_mac(host, opts)
212
+ else
213
+ fetch_pe_on_unix(host, opts)
214
+ end
215
+ end
216
+ end
217
+
218
+ #Classify the master so that it can deploy frictionless packages for a given host.
219
+ # @param [Host] host The host to install pacakges for
220
+ # @api private
221
+ def deploy_frictionless_to_master(host)
222
+ klass = host['platform'].gsub(/-/, '_').gsub(/\./,'')
223
+ klass = "pe_repo::platform::#{klass}"
224
+ on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake nodeclass:add[#{klass},skip]"
225
+ on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake node:add[#{master},,,skip]"
226
+ on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake node:addclass[#{master},#{klass}]"
227
+ on master, puppet("agent -t"), :acceptable_exit_codes => [0,2]
228
+ end
229
+
230
+ #Perform a Puppet Enterprise upgrade or install
231
+ # @param [Array<Host>] hosts The hosts to install or upgrade PE on
232
+ # @param [Hash{Symbol=>Symbol, String}] opts The options
233
+ # @option opts [String] :pe_dir Default directory or URL to pull PE package from
234
+ # (Otherwise uses individual hosts pe_dir)
235
+ # @option opts [String] :pe_ver Default PE version to install or upgrade to
236
+ # (Otherwise uses individual hosts pe_ver)
237
+ # @option opts [String] :pe_ver_win Default PE version to install or upgrade to on Windows hosts
238
+ # (Otherwise uses individual Windows hosts pe_ver)
239
+ # @option opts [Symbol] :type (:install) One of :upgrade or :install
240
+ # @option opts [Boolean] :set_console_password Should we set the PE console password in the answers file? Used during upgrade only.
241
+ # @option opts [Hash<String>] :answers Pre-set answers based upon ENV vars and defaults
242
+ # (See {Beaker::Options::Presets.env_vars})
243
+ #
244
+ # @example
245
+ # do_install(hosts, {:type => :upgrade, :pe_dir => path, :pe_ver => version, :pe_ver_win => version_win})
246
+ #
247
+ # @api private
248
+ #
249
+ def do_install hosts, opts = {}
250
+ masterless = (defined? options) ? options[:masterless] : false
251
+ opts[:masterless] = masterless # has to pass masterless down for answer generation awareness
252
+ opts[:type] = opts[:type] || :install
253
+ unless masterless
254
+ pre30database = version_is_less(opts[:pe_ver] || database['pe_ver'], '3.0')
255
+ pre30master = version_is_less(opts[:pe_ver] || master['pe_ver'], '3.0')
256
+
257
+ unless version_is_less(opts[:pe_ver] || master['pe_ver'], '3.4')
258
+ master['puppetservice'] = 'pe-puppetserver'
259
+ end
260
+ end
261
+
262
+ # Set PE distribution for all the hosts, create working dir
263
+ use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
264
+ hosts.each do |host|
265
+ host['pe_installer'] ||= 'puppet-enterprise-installer'
266
+ if host['platform'] !~ /windows|osx/
267
+ platform = use_all_tar ? 'all' : host['platform']
268
+ version = host['pe_ver'] || opts[:pe_ver]
269
+ host['dist'] = "puppet-enterprise-#{version}-#{platform}"
270
+ elsif host['platform'] =~ /osx/
271
+ version = host['pe_ver'] || opts[:pe_ver]
272
+ host['dist'] = "puppet-enterprise-#{version}-#{host['platform']}"
273
+ elsif host['platform'] =~ /windows/
274
+ version = host[:pe_ver] || opts['pe_ver_win']
275
+ should_install_64bit = !(version_is_less(version, '3.4')) && host.is_x86_64? && !host['install_32'] && !opts['install_32']
276
+ #only install 64bit builds if
277
+ # - we are on pe version 3.4+
278
+ # - we do not have install_32 set on host
279
+ # - we do not have install_32 set globally
280
+ if !(version_is_less(version, '4.0'))
281
+ if should_install_64bit
282
+ host['dist'] = "puppet-agent-#{version}-x64"
283
+ else
284
+ host['dist'] = "puppet-agent-#{version}-x86"
285
+ end
286
+ elsif should_install_64bit
287
+ host['dist'] = "puppet-enterprise-#{version}-x64"
288
+ else
289
+ host['dist'] = "puppet-enterprise-#{version}"
290
+ end
291
+ end
292
+ host['working_dir'] = host.tmpdir(Time.new.strftime("%Y-%m-%d_%H.%M.%S"))
293
+ end
294
+
295
+ fetch_pe(hosts, opts)
296
+
297
+ install_hosts = hosts.dup
298
+ unless masterless
299
+ # If we're installing a database version less than 3.0, ignore the database host
300
+ install_hosts.delete(database) if pre30database and database != master and database != dashboard
301
+ end
302
+
303
+ install_hosts.each do |host|
304
+ if host['platform'] =~ /windows/
305
+ on host, installer_cmd(host, opts)
306
+ if not host.is_cygwin?
307
+ # HACK: for some reason, post install we need to refresh the connection to make puppet available for execution
308
+ host.close
309
+ end
310
+ else
311
+ # We only need answers if we're using the classic installer
312
+ version = host['pe_ver'] || opts[:pe_ver]
313
+ if host['roles'].include?('frictionless') && (! version_is_less(version, '3.2.0'))
314
+ # If We're *not* running the classic installer, we want
315
+ # to make sure the master has packages for us.
316
+ deploy_frictionless_to_master(host)
317
+ on host, installer_cmd(host, opts)
318
+ elsif host['platform'] =~ /osx|eos/
319
+ # If we're not frictionless, we need to run the OSX special-case
320
+ on host, installer_cmd(host, opts)
321
+ #set the certname and master
322
+ on host, puppet("config set server #{master}")
323
+ on host, puppet("config set certname #{host}")
324
+ #run once to request cert
325
+ acceptable_codes = host['platform'] =~ /osx/ ? [1] : [0, 1]
326
+ on host, puppet_agent('-t'), :acceptable_exit_codes => acceptable_codes
327
+ else
328
+ answers = Beaker::Answers.create(opts[:pe_ver] || host['pe_ver'], hosts, opts)
329
+ create_remote_file host, "#{host['working_dir']}/answers", answers.answer_string(host)
330
+ on host, installer_cmd(host, opts)
331
+ end
332
+ end
333
+
334
+ # On each agent, we ensure the certificate is signed then shut down the agent
335
+ sign_certificate_for(host) unless masterless
336
+ stop_agent_on(host)
337
+ end
338
+
339
+ unless masterless
340
+ # Wait for PuppetDB to be totally up and running (post 3.0 version of pe only)
341
+ sleep_until_puppetdb_started(database) unless pre30database
342
+
343
+ # Run the agent once to ensure everything is in the dashboard
344
+ install_hosts.each do |host|
345
+ on host, puppet_agent('-t'), :acceptable_exit_codes => [0,2]
346
+
347
+ # Workaround for PE-1105 when deploying 3.0.0
348
+ # The installer did not respect our database host answers in 3.0.0,
349
+ # and would cause puppetdb to be bounced by the agent run. By sleeping
350
+ # again here, we ensure that if that bounce happens during an upgrade
351
+ # test we won't fail early in the install process.
352
+ if host['pe_ver'] == '3.0.0' and host == database
353
+ sleep_until_puppetdb_started(database)
354
+ end
355
+ end
356
+
357
+ install_hosts.each do |host|
358
+ wait_for_host_in_dashboard(host)
359
+ end
360
+
361
+ if pre30master
362
+ task = 'nodegroup:add_all_nodes group=default'
363
+ else
364
+ task = 'defaultgroup:ensure_default_group'
365
+ end
366
+ on dashboard, "/opt/puppet/bin/rake -sf /opt/puppet/share/puppet-dashboard/Rakefile #{task} RAILS_ENV=production"
367
+
368
+ # Now that all hosts are in the dashbaord, run puppet one more
369
+ # time to configure mcollective
370
+ on install_hosts, puppet_agent('-t'), :acceptable_exit_codes => [0,2]
371
+ end
372
+ end
373
+
374
+ #Install PE based upon host configuration and options
375
+ # @example
376
+ # install_pe
377
+ #
378
+ # @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.
379
+ # Install file names are assumed to be of the format puppet-enterprise-VERSION-PLATFORM.(tar)|(tar.gz)
380
+ # for Unix like systems and puppet-enterprise-VERSION.msi for Windows systems.
381
+ #
382
+ def install_pe
383
+ #process the version files if necessary
384
+ hosts.each do |host|
385
+ host['pe_dir'] ||= options[:pe_dir]
386
+ if host['platform'] =~ /windows/
387
+ host['pe_ver'] = host['pe_ver'] || options['pe_ver'] ||
388
+ Beaker::Options::PEVersionScraper.load_pe_version(host[:pe_dir] || options[:pe_dir], options[:pe_version_file_win])
389
+ else
390
+ host['pe_ver'] = host['pe_ver'] || options['pe_ver'] ||
391
+ Beaker::Options::PEVersionScraper.load_pe_version(host[:pe_dir] || options[:pe_dir], options[:pe_version_file])
392
+ end
393
+ end
394
+ #send in the global options hash
395
+ do_install sorted_hosts, options
396
+ end
397
+
398
+ #Upgrade PE based upon host configuration and options
399
+ # @param [String] path A path (either local directory or a URL to a listing of PE builds).
400
+ # Will contain a LATEST file indicating the latest build to install.
401
+ # This is ignored if a pe_upgrade_ver and pe_upgrade_dir are specified
402
+ # in the host configuration file.
403
+ # @example
404
+ # upgrade_pe("http://neptune.puppetlabs.lan/3.0/ci-ready/")
405
+ #
406
+ # @note Install file names are assumed to be of the format puppet-enterprise-VERSION-PLATFORM.(tar)|(tar.gz)
407
+ # for Unix like systems and puppet-enterprise-VERSION.msi for Windows systems.
408
+ def upgrade_pe path=nil
409
+ set_console_password = false
410
+ # if we are upgrading from something lower than 3.4 then we need to set the pe console password
411
+ if (dashboard[:pe_ver] ? version_is_less(dashboard[:pe_ver], "3.4.0") : true)
412
+ set_console_password = true
413
+ end
414
+ # get new version information
415
+ hosts.each do |host|
416
+ host['pe_dir'] = host['pe_upgrade_dir'] || path
417
+ if host['platform'] =~ /windows/
418
+ host['pe_ver'] = host['pe_upgrade_ver'] || options['pe_upgrade_ver'] ||
419
+ Options::PEVersionScraper.load_pe_version(host['pe_dir'], options[:pe_version_file_win])
420
+ else
421
+ host['pe_ver'] = host['pe_upgrade_ver'] || options['pe_upgrade_ver'] ||
422
+ Options::PEVersionScraper.load_pe_version(host['pe_dir'], options[:pe_version_file])
423
+ end
424
+ if version_is_less(host['pe_ver'], '3.0')
425
+ host['pe_installer'] ||= 'puppet-enterprise-upgrader'
426
+ end
427
+ end
428
+ # send in the global options hash
429
+ do_install(sorted_hosts, options.merge({:type => :upgrade, :set_console_password => set_console_password}))
430
+ options['upgrade'] = true
431
+ end
432
+
433
+ #Create the Higgs install command string based upon the host and options settings. Installation command will be run as a
434
+ #background process. The output of the command will be stored in the provided host['higgs_file'].
435
+ # @param [Host] host The host that Higgs is to be installed on
436
+ # The host object must have the 'working_dir', 'dist' and 'pe_installer' field set correctly.
437
+ # @api private
438
+ def higgs_installer_cmd host
439
+
440
+ "cd #{host['working_dir']}/#{host['dist']} ; nohup ./#{host['pe_installer']} <<<Y > #{host['higgs_file']} 2>&1 &"
441
+
442
+ end
443
+
444
+ #Perform a Puppet Enterprise Higgs install up until web browser interaction is required, runs on linux hosts only.
445
+ # @param [Host] host The host to install higgs on
446
+ # @param [Hash{Symbol=>Symbol, String}] opts The options
447
+ # @option opts [String] :pe_dir Default directory or URL to pull PE package from
448
+ # (Otherwise uses individual hosts pe_dir)
449
+ # @option opts [String] :pe_ver Default PE version to install
450
+ # (Otherwise uses individual hosts pe_ver)
451
+ # @raise [StandardError] When installation times out
452
+ #
453
+ # @example
454
+ # do_higgs_install(master, {:pe_dir => path, :pe_ver => version})
455
+ #
456
+ # @api private
457
+ #
458
+ def do_higgs_install host, opts
459
+ use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
460
+ platform = use_all_tar ? 'all' : host['platform']
461
+ version = host['pe_ver'] || opts[:pe_ver]
462
+ host['dist'] = "puppet-enterprise-#{version}-#{platform}"
463
+
464
+ use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
465
+ host['pe_installer'] ||= 'puppet-enterprise-installer'
466
+ host['working_dir'] = host.tmpdir(Time.new.strftime("%Y-%m-%d_%H.%M.%S"))
467
+
468
+ fetch_pe([host], opts)
469
+
470
+ host['higgs_file'] = "higgs_#{File.basename(host['working_dir'])}.log"
471
+ on host, higgs_installer_cmd(host), opts
472
+
473
+ #wait for output to host['higgs_file']
474
+ #we're all done when we find this line in the PE installation log
475
+ higgs_re = /Please\s+go\s+to\s+https:\/\/.*\s+in\s+your\s+browser\s+to\s+continue\s+installation/m
476
+ res = Result.new(host, 'tmp cmd')
477
+ tries = 10
478
+ attempts = 0
479
+ prev_sleep = 0
480
+ cur_sleep = 1
481
+ while (res.stdout !~ higgs_re) and (attempts < tries)
482
+ res = on host, "cd #{host['working_dir']}/#{host['dist']} && cat #{host['higgs_file']}", :acceptable_exit_codes => (0..255)
483
+ attempts += 1
484
+ sleep( cur_sleep )
485
+ prev_sleep = cur_sleep
486
+ cur_sleep = cur_sleep + prev_sleep
487
+ end
488
+
489
+ if attempts >= tries
490
+ raise "Failed to kick off PE (Higgs) web installation"
491
+ end
492
+ end
493
+
494
+ #Install Higgs up till the point where you need to continue installation in a web browser, defaults to execution
495
+ #on the master node.
496
+ #@param [Host] higgs_host The host to install Higgs on (supported on linux platform only)
497
+ # @example
498
+ # install_higgs
499
+ #
500
+ # @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.
501
+ # Install file names are assumed to be of the format puppet-enterprise-VERSION-PLATFORM.(tar)|(tar.gz).
502
+ #
503
+ def install_higgs( higgs_host = master )
504
+ #process the version files if necessary
505
+ master['pe_dir'] ||= options[:pe_dir]
506
+ master['pe_ver'] = master['pe_ver'] || options['pe_ver'] ||
507
+ Beaker::Options::PEVersionScraper.load_pe_version(master[:pe_dir] || options[:pe_dir], options[:pe_version_file])
508
+ if higgs_host['platform'] =~ /osx|windows/
509
+ raise "Attempting higgs installation on host #{higgs_host.name} with unsupported platform #{higgs_host['platform']}"
510
+ end
511
+ #send in the global options hash
512
+ do_higgs_install higgs_host, options
513
+ end
514
+
515
+ end
516
+ end
517
+ end
518
+ end