beaker 2.35.0 → 2.36.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.
@@ -1,728 +0,0 @@
1
- [ 'aio_defaults', 'pe_defaults', 'puppet_utils', 'windows_utils' ].each do |lib|
2
- require "beaker/dsl/install_utils/#{lib}"
3
- end
4
- require "beaker-answers"
5
- module Beaker
6
- module DSL
7
- module InstallUtils
8
- #
9
- # This module contains methods to help installing/upgrading PE builds - including Higgs installs
10
- #
11
- # To mix this is into a class you need the following:
12
- # * a method *hosts* that yields any hosts implementing
13
- # {Beaker::Host}'s interface to act upon.
14
- # * a method *options* that provides an options hash, see {Beaker::Options::OptionsHash}
15
- # * the module {Beaker::DSL::Roles} that provides access to the various hosts implementing
16
- # {Beaker::Host}'s interface to act upon
17
- # * the module {Beaker::DSL::Wrappers} the provides convenience methods for {Beaker::DSL::Command} creation
18
- module PEUtils
19
- include AIODefaults
20
- include PEDefaults
21
- include PuppetUtils
22
- include WindowsUtils
23
-
24
- # @!macro [new] common_opts
25
- # @param [Hash{Symbol=>String}] opts Options to alter execution.
26
- # @option opts [Boolean] :silent (false) Do not produce log output
27
- # @option opts [Array<Fixnum>] :acceptable_exit_codes ([0]) An array
28
- # (or range) of integer exit codes that should be considered
29
- # acceptable. An error will be thrown if the exit code does not
30
- # match one of the values in this list.
31
- # @option opts [Boolean] :accept_all_exit_codes (false) Consider all
32
- # exit codes as passing.
33
- # @option opts [Boolean] :dry_run (false) Do not actually execute any
34
- # commands on the SUT
35
- # @option opts [String] :stdin (nil) Input to be provided during command
36
- # execution on the SUT.
37
- # @option opts [Boolean] :pty (false) Execute this command in a pseudoterminal.
38
- # @option opts [Boolean] :expect_connection_failure (false) Expect this command
39
- # to result in a connection failure, reconnect and continue execution.
40
- # @option opts [Hash{String=>String}] :environment ({}) These will be
41
- # treated as extra environment variables that should be set before
42
- # running the command.
43
-
44
- #Sort array of hosts so that it has the correct order for PE installation based upon each host's role
45
- #@param subset [Array<Host>] An array of hosts to sort, defaults to global 'hosts' object
46
- # @example
47
- # h = sorted_hosts
48
- #
49
- # @note Order for installation should be
50
- # First : master
51
- # Second: database host (if not same as master)
52
- # Third: dashboard (if not same as master or database)
53
- # Fourth: everything else
54
- #
55
- # @!visibility private
56
- def sorted_hosts subset = hosts
57
- special_nodes = []
58
- [master, database, dashboard].uniq.each do |host|
59
- special_nodes << host if host != nil && subset.include?(host)
60
- end
61
- real_agents = agents - special_nodes
62
- real_agents = real_agents.delete_if{ |host| !subset.include?(host) }
63
- special_nodes + real_agents
64
- end
65
-
66
- #Create the PE install command string based upon the host and options settings
67
- # @param [Host] host The host that PE is to be installed on
68
- # For UNIX machines using the full PE installer, the host object must have the 'pe_installer' field set correctly.
69
- # @param [Hash{Symbol=>String}] opts The options
70
- # @option opts [String] :pe_ver Default PE version to install or upgrade to
71
- # (Otherwise uses individual hosts pe_ver)
72
- # @option opts [Boolean] :pe_debug (false) Should we run the installer in debug mode?
73
- # @example
74
- # on host, "#{installer_cmd(host, opts)} -a #{host['working_dir']}/answers"
75
- # @api private
76
- def installer_cmd(host, opts)
77
- version = host['pe_ver'] || opts[:pe_ver]
78
- # Frictionless install didn't exist pre-3.2.0, so in that case we fall
79
- # through and do a regular install.
80
- if host['roles'].include? 'frictionless' and ! version_is_less(version, '3.2.0')
81
- # PE 3.4 introduced the ability to pass in config options to the bash script in the form
82
- # of <section>:<key>=<value>
83
- frictionless_install_opts = []
84
- if host.has_key?('frictionless_options') and ! version_is_less(version, '3.4.0')
85
- # since we have options to pass in, we need to tell the bash script
86
- host['frictionless_options'].each do |section, settings|
87
- settings.each do |key, value|
88
- frictionless_install_opts << "#{section}:#{key}=#{value}"
89
- end
90
- end
91
- end
92
-
93
- pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -x' : ''
94
- if host['platform'] =~ /aix/ then
95
- curl_opts = '--tlsv1 -O'
96
- else
97
- curl_opts = '--tlsv1 -kO'
98
- end
99
- "cd #{host['working_dir']} && curl #{curl_opts} https://#{master}:8140/packages/#{version}/install.bash && bash#{pe_debug} install.bash #{frictionless_install_opts.join(' ')}".strip
100
- elsif host['platform'] =~ /osx/
101
- version = host['pe_ver'] || opts[:pe_ver]
102
- pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -verboseR' : ''
103
- "cd #{host['working_dir']} && hdiutil attach #{host['dist']}.dmg && installer#{pe_debug} -pkg /Volumes/puppet-enterprise-#{version}/puppet-enterprise-installer-#{version}.pkg -target /"
104
- elsif host['platform'] =~ /eos/
105
- host.install_from_file("puppet-enterprise-#{version}-#{host['platform']}.swix")
106
- else
107
- pe_debug = host[:pe_debug] || opts[:pe_debug] ? ' -D' : ''
108
- "cd #{host['working_dir']}/#{host['dist']} && ./#{host['pe_installer']}#{pe_debug} -a #{host['working_dir']}/answers"
109
- end
110
- end
111
-
112
- #Determine the PE package to download/upload on a mac host, download/upload that package onto the host.
113
- # Assumed file name format: puppet-enterprise-3.3.0-rc1-559-g97f0833-osx-10.9-x86_64.dmg.
114
- # @param [Host] host The mac host to download/upload and unpack PE onto
115
- # @param [Hash{Symbol=>Symbol, String}] opts The options
116
- # @option opts [String] :pe_dir Default directory or URL to pull PE package from
117
- # (Otherwise uses individual hosts pe_dir)
118
- # @option opts [Boolean] :fetch_local_then_push_to_host determines whether
119
- # you use Beaker as the middleman for this (true), or curl the
120
- # file from the host (false; default behavior)
121
- # @api private
122
- def fetch_pe_on_mac(host, opts)
123
- path = host['pe_dir'] || opts[:pe_dir]
124
- local = File.directory?(path)
125
- filename = "#{host['dist']}"
126
- extension = ".dmg"
127
- if local
128
- if not File.exists?("#{path}/#{filename}#{extension}")
129
- raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
130
- end
131
- scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
132
- else
133
- if not link_exists?("#{path}/#{filename}#{extension}")
134
- raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
135
- end
136
- if opts[:fetch_local_then_push_to_host]
137
- fetch_and_push_pe(host, path, filename, extension)
138
- else
139
- on host, "cd #{host['working_dir']}; curl -O #{path}/#{filename}#{extension}"
140
- end
141
- end
142
- end
143
-
144
- #Determine the PE package to download/upload on a windows host, download/upload that package onto the host.
145
- #Assumed file name format: puppet-enterprise-3.3.0-rc1-559-g97f0833.msi
146
- # @param [Host] host The windows host to download/upload and unpack PE onto
147
- # @param [Hash{Symbol=>Symbol, String}] opts The options
148
- # @option opts [String] :pe_dir Default directory or URL to pull PE package from
149
- # (Otherwise uses individual hosts pe_dir)
150
- # @option opts [String] :pe_ver_win Default PE version to install or upgrade to
151
- # (Otherwise uses individual hosts pe_ver)
152
- # @option opts [Boolean] :fetch_local_then_push_to_host determines whether
153
- # you use Beaker as the middleman for this (true), or curl the
154
- # file from the host (false; default behavior)
155
- # @api private
156
- def fetch_pe_on_windows(host, opts)
157
- path = host['pe_dir'] || opts[:pe_dir]
158
- local = File.directory?(path)
159
- version = host['pe_ver'] || opts[:pe_ver_win]
160
- filename = "#{host['dist']}"
161
- extension = ".msi"
162
- if local
163
- if not File.exists?("#{path}/#{filename}#{extension}")
164
- raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
165
- end
166
- scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
167
- else
168
- if not link_exists?("#{path}/#{filename}#{extension}")
169
- raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
170
- end
171
- if opts[:fetch_local_then_push_to_host]
172
- fetch_and_push_pe(host, path, filename, extension)
173
- on host, "cd #{host['working_dir']}; chmod 644 #{filename}#{extension}"
174
- elsif host.is_cygwin?
175
- on host, "cd #{host['working_dir']}; curl -O #{path}/#{filename}#{extension}"
176
- else
177
- on host, powershell("$webclient = New-Object System.Net.WebClient; $webclient.DownloadFile('#{path}/#{filename}#{extension}','#{host['working_dir']}\\#{filename}#{extension}')")
178
- end
179
- end
180
- end
181
-
182
- #Determine the PE package to download/upload on a unix style host, download/upload that package onto the host
183
- #and unpack it.
184
- # @param [Host] host The unix style host to download/upload and unpack PE onto
185
- # @param [Hash{Symbol=>Symbol, String}] opts The options
186
- # @option opts [String] :pe_dir Default directory or URL to pull PE package from
187
- # (Otherwise uses individual hosts pe_dir)
188
- # @option opts [Boolean] :fetch_local_then_push_to_host determines whether
189
- # you use Beaker as the middleman for this (true), or curl the
190
- # file from the host (false; default behavior)
191
- # @api private
192
- def fetch_pe_on_unix(host, opts)
193
- path = host['pe_dir'] || opts[:pe_dir]
194
- local = File.directory?(path)
195
- filename = "#{host['dist']}"
196
- if local
197
- extension = File.exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
198
- if not File.exists?("#{path}/#{filename}#{extension}")
199
- raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
200
- end
201
- scp_to host, "#{path}/#{filename}#{extension}", "#{host['working_dir']}/#{filename}#{extension}"
202
- if extension =~ /gz/
203
- on host, "cd #{host['working_dir']}; gunzip #{filename}#{extension}"
204
- end
205
- if extension =~ /tar/
206
- on host, "cd #{host['working_dir']}; tar -xvf #{filename}.tar"
207
- end
208
- else
209
- if host['platform'] =~ /eos/
210
- extension = '.swix'
211
- else
212
- extension = link_exists?("#{path}/#{filename}.tar.gz") ? ".tar.gz" : ".tar"
213
- end
214
- if not link_exists?("#{path}/#{filename}#{extension}")
215
- raise "attempting installation on #{host}, #{path}/#{filename}#{extension} does not exist"
216
- end
217
-
218
- if host['platform'] =~ /eos/
219
- host.get_remote_file("#{path}/#{filename}#{extension}")
220
- else
221
- unpack = 'tar -xvf -'
222
- unpack = extension =~ /gz/ ? 'gunzip | ' + unpack : unpack
223
- if opts[:fetch_local_then_push_to_host]
224
- fetch_and_push_pe(host, path, filename, extension)
225
- command_file_push = 'cat '
226
- else
227
- command_file_push = "curl #{path}/"
228
- end
229
- on host, "cd #{host['working_dir']}; #{command_file_push}#{filename}#{extension} | #{unpack}"
230
-
231
- end
232
- end
233
- end
234
-
235
- #Determine the PE package to download/upload per-host, download/upload that package onto the host
236
- #and unpack it.
237
- # @param [Array<Host>] hosts The hosts to download/upload and unpack PE onto
238
- # @param [Hash{Symbol=>Symbol, String}] opts The options
239
- # @option opts [String] :pe_dir Default directory or URL to pull PE package from
240
- # (Otherwise uses individual hosts pe_dir)
241
- # @option opts [String] :pe_ver Default PE version to install or upgrade to
242
- # (Otherwise uses individual hosts pe_ver)
243
- # @option opts [String] :pe_ver_win Default PE version to install or upgrade to on Windows hosts
244
- # (Otherwise uses individual Windows hosts pe_ver)
245
- # @option opts [Boolean] :fetch_local_then_push_to_host determines whether
246
- # you use Beaker as the middleman for this (true), or curl the
247
- # file from the host (false; default behavior)
248
- # @api private
249
- def fetch_pe(hosts, opts)
250
- hosts.each do |host|
251
- # We install Puppet from the master for frictionless installs, so we don't need to *fetch* anything
252
- next if host['roles'].include?('frictionless') && (! version_is_less(opts[:pe_ver] || host['pe_ver'], '3.2.0'))
253
-
254
- if host['platform'] =~ /windows/
255
- fetch_pe_on_windows(host, opts)
256
- elsif host['platform'] =~ /osx/
257
- fetch_pe_on_mac(host, opts)
258
- else
259
- fetch_pe_on_unix(host, opts)
260
- end
261
- end
262
- end
263
-
264
- #Classify the master so that it can deploy frictionless packages for a given host.
265
- # @param [Host] host The host to install pacakges for
266
- # @api private
267
- def deploy_frictionless_to_master(host)
268
- klass = host['platform'].gsub(/-/, '_').gsub(/\./,'')
269
- klass = "pe_repo::platform::#{klass}"
270
- if version_is_less(host['pe_ver'], '3.8')
271
- # use the old rake tasks
272
- on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake nodeclass:add[#{klass},skip]"
273
- on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake node:add[#{master},,,skip]"
274
- on dashboard, "cd /opt/puppet/share/puppet-dashboard && /opt/puppet/bin/bundle exec /opt/puppet/bin/rake node:addclass[#{master},#{klass}]"
275
- on master, puppet("agent -t"), :acceptable_exit_codes => [0,2]
276
- else
277
- # the new hotness
278
- begin
279
- require 'scooter'
280
- rescue LoadError => e
281
- @logger.notify('WARNING: gem scooter is required for frictionless installation post 3.8')
282
- raise e
283
- end
284
- dispatcher = Scooter::HttpDispatchers::ConsoleDispatcher.new(dashboard)
285
-
286
- # Check if we've already created a frictionless agent node group
287
- # to avoid errors creating the same node group when the beaker hosts file contains
288
- # multiple hosts with the same platform
289
- node_group = dispatcher.get_node_group_by_name('Beaker Frictionless Agent')
290
- if node_group.nil? || node_group.empty?
291
- node_group = {}
292
- node_group['name'] = "Beaker Frictionless Agent"
293
- # Pin the master to the node
294
- node_group['rule'] = [ "and", [ '=', 'name', master.to_s ]]
295
- node_group['classes'] ||= {}
296
- end
297
-
298
- # add the pe_repo platform class
299
- node_group['classes'][klass] = {}
300
-
301
- dispatcher.create_new_node_group_model(node_group)
302
- on master, puppet("agent -t"), :acceptable_exit_codes => [0,2]
303
- end
304
- end
305
-
306
- #Perform a Puppet Enterprise upgrade or install
307
- # @param [Array<Host>] hosts The hosts to install or upgrade PE on
308
- # @param [Hash{Symbol=>Symbol, String}] opts The options
309
- # @option opts [String] :pe_dir Default directory or URL to pull PE package from
310
- # (Otherwise uses individual hosts pe_dir)
311
- # @option opts [String] :pe_ver Default PE version to install or upgrade to
312
- # (Otherwise uses individual hosts pe_ver)
313
- # @option opts [String] :pe_ver_win Default PE version to install or upgrade to on Windows hosts
314
- # (Otherwise uses individual Windows hosts pe_ver)
315
- # @option opts [Symbol] :type (:install) One of :upgrade or :install
316
- # @option opts [Boolean] :set_console_password Should we set the PE console password in the answers file? Used during upgrade only.
317
- # @option opts [Hash<String>] :answers Pre-set answers based upon ENV vars and defaults
318
- # (See {Beaker::Options::Presets.env_vars})
319
- # @option opts [Boolean] :fetch_local_then_push_to_host determines whether
320
- # you use Beaker as the middleman for this (true), or curl the
321
- # file from the host (false; default behavior)
322
- # @option opts [Boolean] :masterless Are we performing a masterless installation?
323
- #
324
- # @example
325
- # do_install(hosts, {:type => :upgrade, :pe_dir => path, :pe_ver => version, :pe_ver_win => version_win})
326
- #
327
- # @note on windows, the +:ruby_arch+ host parameter can determine in addition
328
- # to other settings whether the 32 or 64bit install is used
329
- #
330
- # @note for puppet-agent install options, refer to
331
- # {Beaker::DSL::InstallUtils::FOSSUtils#install_puppet_agent_pe_promoted_repo_on}
332
- #
333
- # @api private
334
- #
335
- def do_install hosts, opts = {}
336
- masterless = opts[:masterless]
337
- opts[:type] = opts[:type] || :install
338
- unless masterless
339
- pre30database = version_is_less(opts[:pe_ver] || database['pe_ver'], '3.0')
340
- pre30master = version_is_less(opts[:pe_ver] || master['pe_ver'], '3.0')
341
- end
342
-
343
- pe_versions = ( [] << opts['pe_ver'] << hosts.map{ |host| host['pe_ver'] } ).flatten.compact
344
- agent_only_check_needed = version_is_less('3.99', max_version(pe_versions, '3.8'))
345
- if agent_only_check_needed
346
- hosts_agent_only, hosts_not_agent_only = create_agent_specified_arrays(hosts)
347
- else
348
- hosts_agent_only, hosts_not_agent_only = [], hosts.dup
349
- end
350
-
351
- # Set PE distribution for all the hosts, create working dir
352
- use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
353
- hosts.each do |host|
354
- next if agent_only_check_needed && hosts_agent_only.include?(host)
355
- host['pe_installer'] ||= 'puppet-enterprise-installer'
356
- if host['platform'] !~ /windows|osx/
357
- platform = use_all_tar ? 'all' : host['platform']
358
- version = host['pe_ver'] || opts[:pe_ver]
359
- host['dist'] = "puppet-enterprise-#{version}-#{platform}"
360
- elsif host['platform'] =~ /osx/
361
- version = host['pe_ver'] || opts[:pe_ver]
362
- host['dist'] = "puppet-enterprise-#{version}-#{host['platform']}"
363
- elsif host['platform'] =~ /windows/
364
- version = host[:pe_ver] || opts['pe_ver_win']
365
- is_config_32 = true == (host['ruby_arch'] == 'x86') || host['install_32'] || opts['install_32']
366
- should_install_64bit = !(version_is_less(version, '3.4')) && host.is_x86_64? && !is_config_32
367
- #only install 64bit builds if
368
- # - we are on pe version 3.4+
369
- # - we do not have install_32 set on host
370
- # - we do not have install_32 set globally
371
- if !(version_is_less(version, '3.99'))
372
- if should_install_64bit
373
- host['dist'] = "puppet-agent-#{version}-x64"
374
- else
375
- host['dist'] = "puppet-agent-#{version}-x86"
376
- end
377
- elsif should_install_64bit
378
- host['dist'] = "puppet-enterprise-#{version}-x64"
379
- else
380
- host['dist'] = "puppet-enterprise-#{version}"
381
- end
382
- end
383
- host['working_dir'] = host.tmpdir(Time.new.strftime("%Y-%m-%d_%H.%M.%S"))
384
- end
385
-
386
- fetch_pe(hosts_not_agent_only, opts)
387
-
388
- install_hosts = hosts.dup
389
- unless masterless
390
- # If we're installing a database version less than 3.0, ignore the database host
391
- install_hosts.delete(database) if pre30database and database != master and database != dashboard
392
- end
393
-
394
- install_hosts.each do |host|
395
- if agent_only_check_needed && hosts_agent_only.include?(host)
396
- host['type'] = 'aio'
397
- install_puppet_agent_pe_promoted_repo_on(host, { :puppet_agent_version => host[:puppet_agent_version] || opts[:puppet_agent_version],
398
- :puppet_agent_sha => host[:puppet_agent_sha] || opts[:puppet_agent_sha],
399
- :pe_ver => host[:pe_ver] || opts[:pe_ver],
400
- :puppet_collection => host[:puppet_collection] || opts[:puppet_collection] })
401
- # 1 since no certificate found and waitforcert disabled
402
- acceptable_exit_codes = [0, 1]
403
- acceptable_exit_codes << 2 if opts[:type] == :upgrade
404
- setup_defaults_and_config_helper_on(host, master, acceptable_exit_codes)
405
- elsif host['platform'] =~ /windows/
406
- opts = { :debug => host[:pe_debug] || opts[:pe_debug] }
407
- msi_path = "#{host['working_dir']}\\#{host['dist']}.msi"
408
- install_msi_on(host, msi_path, {}, opts)
409
-
410
- # 1 since no certificate found and waitforcert disabled
411
- acceptable_exit_codes = 1
412
- setup_defaults_and_config_helper_on(host, master, acceptable_exit_codes)
413
- else
414
- # We only need answers if we're using the classic installer
415
- version = host['pe_ver'] || opts[:pe_ver]
416
- if host['roles'].include?('frictionless') && (! version_is_less(version, '3.2.0'))
417
- # If We're *not* running the classic installer, we want
418
- # to make sure the master has packages for us.
419
- if host['platform'] != master['platform'] # only need to do this if platform differs
420
- deploy_frictionless_to_master(host)
421
- end
422
- on host, installer_cmd(host, opts)
423
- configure_type_defaults_on(host)
424
- elsif host['platform'] =~ /osx|eos/
425
- # If we're not frictionless, we need to run the OSX special-case
426
- on host, installer_cmd(host, opts)
427
- acceptable_codes = host['platform'] =~ /osx/ ? [1] : [0, 1]
428
- setup_defaults_and_config_helper_on(host, master, acceptable_codes)
429
- else
430
- answers = BeakerAnswers::Answers.create(opts[:pe_ver] || host['pe_ver'], hosts, opts)
431
- create_remote_file host, "#{host['working_dir']}/answers", answers.answer_string(host)
432
- on host, installer_cmd(host, opts)
433
- configure_type_defaults_on(host)
434
- end
435
- end
436
-
437
- # On each agent, we ensure the certificate is signed then shut down the agent
438
- sign_certificate_for(host) unless masterless
439
- stop_agent_on(host)
440
- end
441
-
442
- unless masterless
443
- # Wait for PuppetDB to be totally up and running (post 3.0 version of pe only)
444
- sleep_until_puppetdb_started(database) unless pre30database
445
-
446
- # Run the agent once to ensure everything is in the dashboard
447
- install_hosts.each do |host|
448
- on host, puppet_agent('-t'), :acceptable_exit_codes => [0,2]
449
-
450
- # Workaround for PE-1105 when deploying 3.0.0
451
- # The installer did not respect our database host answers in 3.0.0,
452
- # and would cause puppetdb to be bounced by the agent run. By sleeping
453
- # again here, we ensure that if that bounce happens during an upgrade
454
- # test we won't fail early in the install process.
455
- if host['pe_ver'] == '3.0.0' and host == database
456
- sleep_until_puppetdb_started(database)
457
- end
458
- end
459
-
460
- install_hosts.each do |host|
461
- wait_for_host_in_dashboard(host)
462
- end
463
-
464
- # only appropriate for pre-3.9 builds
465
- if version_is_less(master[:pe_ver], '3.99')
466
- if pre30master
467
- task = 'nodegroup:add_all_nodes group=default'
468
- else
469
- task = 'defaultgroup:ensure_default_group'
470
- end
471
- on dashboard, "/opt/puppet/bin/rake -sf /opt/puppet/share/puppet-dashboard/Rakefile #{task} RAILS_ENV=production"
472
- end
473
-
474
- # Now that all hosts are in the dashbaord, run puppet one more
475
- # time to configure mcollective
476
- on install_hosts, puppet_agent('-t'), :acceptable_exit_codes => [0,2]
477
- end
478
- end
479
-
480
- # Builds the agent_only and not_agent_only arrays needed for installation.
481
- #
482
- # @param [Array<Host>] hosts hosts to split up into the arrays
483
- #
484
- # @note should only be called against versions 4.0+, as this method
485
- # assumes AIO packages will be required.
486
- #
487
- # @note agent_only hosts with the :pe_ver setting < 4.0 will not be
488
- # included in the agent_only array, as AIO install can only happen
489
- # in versions > 4.0
490
- #
491
- # @api private
492
- # @return [Array<Host>, Array<Host>]
493
- # the array of hosts to do an agent_only install on and
494
- # the array of hosts to do our usual install methods on
495
- def create_agent_specified_arrays(hosts)
496
- hosts_agent_only = []
497
- hosts_not_agent_only = []
498
- non_agent_only_roles = %w(master database dashboard console frictionless)
499
- hosts.each do |host|
500
- if host['roles'].none? {|role| non_agent_only_roles.include?(role) }
501
- if !aio_version?(host)
502
- hosts_not_agent_only << host
503
- else
504
- hosts_agent_only << host
505
- end
506
- else
507
- hosts_not_agent_only << host
508
- end
509
- end
510
- return hosts_agent_only, hosts_not_agent_only
511
- end
512
-
513
- # Helper for setting up pe_defaults & setting up the cert on the host
514
- # @param [Host] host host to setup
515
- # @param [Host] master the master host, for setting up the relationship
516
- # @param [Array<Fixnum>] acceptable_exit_codes The exit codes that we want to ignore
517
- #
518
- # @return nil
519
- # @api private
520
- def setup_defaults_and_config_helper_on(host, master, acceptable_exit_codes=nil)
521
- configure_type_defaults_on(host)
522
- #set the certname and master
523
- on host, puppet("config set server #{master}")
524
- on host, puppet("config set certname #{host}")
525
- #run once to request cert
526
- on host, puppet_agent('-t'), :acceptable_exit_codes => acceptable_exit_codes
527
- end
528
-
529
- #Install PE based on global hosts with global options
530
- #@see #install_pe_on
531
- def install_pe
532
- install_pe_on(hosts, options)
533
- end
534
-
535
- #Install PE based upon host configuration and options
536
- #
537
- # @param [Host, Array<Host>] install_hosts One or more hosts to act upon
538
- # @!macro common_opts
539
- # @option opts [Boolean] :masterless Are we performing a masterless installation?
540
- # @option opts [String] :puppet_agent_version Version of puppet-agent to install. Required for PE agent
541
- # only hosts on 4.0+
542
- # @option opts [String] :puppet_agent_sha The sha of puppet-agent to install, defaults to puppet_agent_version.
543
- # Required for PE agent only hosts on 4.0+
544
- # @option opts [String] :pe_ver The version of PE (will also use host['pe_ver']), defaults to '4.0'
545
- # @option opts [String] :puppet_collection The puppet collection for puppet-agent install.
546
- #
547
- # @example
548
- # install_pe_on(hosts, {})
549
- #
550
- # @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.
551
- # Install file names are assumed to be of the format puppet-enterprise-VERSION-PLATFORM.(tar)|(tar.gz)
552
- # for Unix like systems and puppet-enterprise-VERSION.msi for Windows systems.
553
- #
554
- # @note For further installation parameters (such as puppet-agent install)
555
- # options, refer to {#do_install} documentation
556
- #
557
- def install_pe_on(install_hosts, opts)
558
- confine_block(:to, {}, install_hosts) do
559
- sorted_hosts.each do |host|
560
- #process the version files if necessary
561
- host['pe_dir'] ||= opts[:pe_dir]
562
- if host['platform'] =~ /windows/
563
- # we don't need the pe_version if:
564
- # * master pe_ver > 4.0
565
- if not (!opts[:masterless] && master[:pe_ver] && !version_is_less(master[:pe_ver], '3.99'))
566
- host['pe_ver'] ||= Beaker::Options::PEVersionScraper.load_pe_version(host[:pe_dir] || opts[:pe_dir], opts[:pe_version_file_win])
567
- else
568
- # inherit the master's version
569
- host['pe_ver'] ||= master[:pe_ver]
570
- end
571
- else
572
- host['pe_ver'] ||= Beaker::Options::PEVersionScraper.load_pe_version(host[:pe_dir] || opts[:pe_dir], opts[:pe_version_file])
573
- end
574
- end
575
- do_install sorted_hosts, opts
576
- end
577
- end
578
-
579
- #Upgrade PE based upon global host configuration and global options
580
- #@see #upgrade_pe_on
581
- def upgrade_pe path=nil
582
- upgrade_pe_on(hosts, options, path)
583
- end
584
-
585
- #Upgrade PE based upon host configuration and options
586
- # @param [Host, Array<Host>] upgrade_hosts One or more hosts to act upon
587
- # @!macro common_opts
588
- # @param [String] path A path (either local directory or a URL to a listing of PE builds).
589
- # Will contain a LATEST file indicating the latest build to install.
590
- # This is ignored if a pe_upgrade_ver and pe_upgrade_dir are specified
591
- # in the host configuration file.
592
- # @example
593
- # upgrade_pe_on(agents, {}, "http://neptune.puppetlabs.lan/3.0/ci-ready/")
594
- #
595
- # @note Install file names are assumed to be of the format puppet-enterprise-VERSION-PLATFORM.(tar)|(tar.gz)
596
- # for Unix like systems and puppet-enterprise-VERSION.msi for Windows systems.
597
- def upgrade_pe_on upgrade_hosts, opts, path=nil
598
- confine_block(:to, {}, upgrade_hosts) do
599
- set_console_password = false
600
- # if we are upgrading from something lower than 3.4 then we need to set the pe console password
601
- if (dashboard[:pe_ver] ? version_is_less(dashboard[:pe_ver], "3.4.0") : true)
602
- set_console_password = true
603
- end
604
- # get new version information
605
- hosts.each do |host|
606
- host['pe_dir'] = host['pe_upgrade_dir'] || path
607
- if host['platform'] =~ /windows/
608
- host['pe_ver'] = host['pe_upgrade_ver'] || opts['pe_upgrade_ver'] ||
609
- Options::PEVersionScraper.load_pe_version(host['pe_dir'], opts[:pe_version_file_win])
610
- else
611
- host['pe_ver'] = host['pe_upgrade_ver'] || opts['pe_upgrade_ver'] ||
612
- Options::PEVersionScraper.load_pe_version(host['pe_dir'], opts[:pe_version_file])
613
- end
614
- if version_is_less(host['pe_ver'], '3.0')
615
- host['pe_installer'] ||= 'puppet-enterprise-upgrader'
616
- end
617
- end
618
- do_install(sorted_hosts, opts.merge({:type => :upgrade, :set_console_password => set_console_password}))
619
- opts['upgrade'] = true
620
- end
621
- end
622
-
623
- #Create the Higgs install command string based upon the host and options settings. Installation command will be run as a
624
- #background process. The output of the command will be stored in the provided host['higgs_file'].
625
- # @param [Host] host The host that Higgs is to be installed on
626
- # The host object must have the 'working_dir', 'dist' and 'pe_installer' field set correctly.
627
- # @api private
628
- def higgs_installer_cmd host
629
-
630
- "cd #{host['working_dir']}/#{host['dist']} ; nohup ./#{host['pe_installer']} <<<Y > #{host['higgs_file']} 2>&1 &"
631
-
632
- end
633
-
634
- #Perform a Puppet Enterprise Higgs install up until web browser interaction is required, runs on linux hosts only.
635
- # @param [Host] host The host to install higgs on
636
- # @param [Hash{Symbol=>Symbol, String}] opts The options
637
- # @option opts [String] :pe_dir Default directory or URL to pull PE package from
638
- # (Otherwise uses individual hosts pe_dir)
639
- # @option opts [String] :pe_ver Default PE version to install
640
- # (Otherwise uses individual hosts pe_ver)
641
- # @option opts [Boolean] :fetch_local_then_push_to_host determines whether
642
- # you use Beaker as the middleman for this (true), or curl the
643
- # file from the host (false; default behavior)
644
- # @raise [StandardError] When installation times out
645
- #
646
- # @example
647
- # do_higgs_install(master, {:pe_dir => path, :pe_ver => version})
648
- #
649
- # @api private
650
- #
651
- def do_higgs_install host, opts
652
- use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
653
- platform = use_all_tar ? 'all' : host['platform']
654
- version = host['pe_ver'] || opts[:pe_ver]
655
- host['dist'] = "puppet-enterprise-#{version}-#{platform}"
656
-
657
- use_all_tar = ENV['PE_USE_ALL_TAR'] == 'true'
658
- host['pe_installer'] ||= 'puppet-enterprise-installer'
659
- host['working_dir'] = host.tmpdir(Time.new.strftime("%Y-%m-%d_%H.%M.%S"))
660
-
661
- fetch_pe([host], opts)
662
-
663
- host['higgs_file'] = "higgs_#{File.basename(host['working_dir'])}.log"
664
- on host, higgs_installer_cmd(host), opts
665
-
666
- #wait for output to host['higgs_file']
667
- #we're all done when we find this line in the PE installation log
668
- higgs_re = /Please\s+go\s+to\s+https:\/\/.*\s+in\s+your\s+browser\s+to\s+continue\s+installation/m
669
- res = Result.new(host, 'tmp cmd')
670
- tries = 10
671
- attempts = 0
672
- prev_sleep = 0
673
- cur_sleep = 1
674
- while (res.stdout !~ higgs_re) and (attempts < tries)
675
- res = on host, "cd #{host['working_dir']}/#{host['dist']} && cat #{host['higgs_file']}", :accept_all_exit_codes => true
676
- attempts += 1
677
- sleep( cur_sleep )
678
- prev_sleep = cur_sleep
679
- cur_sleep = cur_sleep + prev_sleep
680
- end
681
-
682
- if attempts >= tries
683
- raise "Failed to kick off PE (Higgs) web installation"
684
- end
685
- end
686
-
687
- #Install Higgs up till the point where you need to continue installation in a web browser, defaults to execution
688
- #on the master node.
689
- #@param [Host] higgs_host The host to install Higgs on (supported on linux platform only)
690
- # @example
691
- # install_higgs
692
- #
693
- # @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.
694
- # Install file names are assumed to be of the format puppet-enterprise-VERSION-PLATFORM.(tar)|(tar.gz).
695
- #
696
- def install_higgs( higgs_host = master )
697
- #process the version files if necessary
698
- master['pe_dir'] ||= options[:pe_dir]
699
- master['pe_ver'] = master['pe_ver'] || options['pe_ver'] ||
700
- Beaker::Options::PEVersionScraper.load_pe_version(master[:pe_dir] || options[:pe_dir], options[:pe_version_file])
701
- if higgs_host['platform'] =~ /osx|windows/
702
- raise "Attempting higgs installation on host #{higgs_host.name} with unsupported platform #{higgs_host['platform']}"
703
- end
704
- #send in the global options hash
705
- do_higgs_install higgs_host, options
706
- end
707
-
708
- # Grabs the pe file from a remote host to the machine running Beaker, then
709
- # scp's the file out to the host.
710
- #
711
- # @param [Host] host The host to install on
712
- # @param [String] path path to the install file
713
- # @param [String] filename the filename of the pe file (without the extension)
714
- # @param [String] extension the extension of the pe file
715
- # @param [String] local_dir the directory to store the pe file in on
716
- # the Beaker-running-machine
717
- #
718
- # @api private
719
- # @return nil
720
- def fetch_and_push_pe(host, path, filename, extension, local_dir='tmp/pe')
721
- fetch_http_file("#{path}", "#{filename}#{extension}", local_dir)
722
- scp_to host, "#{local_dir}/#{filename}#{extension}", host['working_dir']
723
- end
724
-
725
- end
726
- end
727
- end
728
- end