beaker 2.18.3 → 2.19.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 (63) hide show
  1. checksums.yaml +8 -8
  2. data/HISTORY.md +439 -2
  3. data/acceptance/lib/beaker/acceptance/install_utils.rb +58 -0
  4. data/acceptance/pre_suite/puppet_git/install.rb +6 -65
  5. data/acceptance/tests/foss_utils/clone_git_repo_on.rb +49 -0
  6. data/beaker.gemspec +2 -0
  7. data/lib/beaker/dsl/helpers/web_helpers.rb +2 -1
  8. data/lib/beaker/dsl/install_utils/aio_defaults.rb +0 -2
  9. data/lib/beaker/dsl/install_utils/foss_utils.rb +97 -60
  10. data/lib/beaker/dsl/install_utils/pe_utils.rb +30 -53
  11. data/lib/beaker/dsl/install_utils/puppet_utils.rb +43 -0
  12. data/lib/beaker/dsl/install_utils/windows_utils.rb +144 -0
  13. data/lib/beaker/dsl/roles.rb +20 -3
  14. data/lib/beaker/dsl/structure.rb +14 -3
  15. data/lib/beaker/host.rb +24 -3
  16. data/lib/beaker/host/unix/pkg.rb +9 -0
  17. data/lib/beaker/host/windows/exec.rb +3 -0
  18. data/lib/beaker/host_prebuilt_steps.rb +5 -9
  19. data/lib/beaker/hypervisor/aws_sdk.rb +22 -18
  20. data/lib/beaker/hypervisor/docker.rb +7 -0
  21. data/lib/beaker/hypervisor/vmpooler.rb +4 -0
  22. data/lib/beaker/logger.rb +12 -1
  23. data/lib/beaker/options/command_line_parser.rb +9 -0
  24. data/lib/beaker/options/options_hash.rb +3 -296
  25. data/lib/beaker/options/parser.rb +12 -0
  26. data/lib/beaker/options/presets.rb +0 -1
  27. data/lib/beaker/ssh_connection.rb +48 -23
  28. data/lib/beaker/test_case.rb +1 -1
  29. data/lib/beaker/version.rb +1 -1
  30. data/spec/beaker/dsl/helpers/web_helpers_spec.rb +10 -1
  31. data/spec/beaker/dsl/install_utils/foss_utils_spec.rb +194 -49
  32. data/spec/beaker/dsl/install_utils/pe_utils_spec.rb +112 -22
  33. data/spec/beaker/dsl/install_utils/puppet_utils_spec.rb +57 -0
  34. data/spec/beaker/dsl/install_utils/windows_utils_spec.rb +132 -0
  35. data/spec/beaker/dsl/roles_spec.rb +36 -5
  36. data/spec/beaker/dsl/structure_spec.rb +9 -2
  37. data/spec/beaker/host/unix/pkg_spec.rb +26 -6
  38. data/spec/beaker/host_prebuilt_steps_spec.rb +3 -2
  39. data/spec/beaker/host_spec.rb +18 -0
  40. data/spec/beaker/hypervisor/aixer_spec.rb +1 -1
  41. data/spec/beaker/hypervisor/aws_sdk_spec.rb +595 -58
  42. data/spec/beaker/hypervisor/docker_spec.rb +2 -1
  43. data/spec/beaker/hypervisor/solaris_spec.rb +1 -0
  44. data/spec/beaker/hypervisor/vagrant_spec.rb +2 -1
  45. data/spec/beaker/logger_spec.rb +39 -0
  46. data/spec/beaker/options/command_line_parser_spec.rb +2 -2
  47. data/spec/beaker/options/options_hash_spec.rb +1 -102
  48. data/spec/beaker/options/parser_spec.rb +19 -0
  49. data/spec/beaker/options/pe_version_scaper_spec.rb +11 -1
  50. data/spec/beaker/options/presets_spec.rb +8 -0
  51. data/spec/beaker/ssh_connection_spec.rb +39 -21
  52. data/spec/helpers.rb +9 -3
  53. data/spec/mocks.rb +2 -0
  54. metadata +34 -11
  55. data/lib/beaker/answers.rb +0 -143
  56. data/lib/beaker/answers/version20.rb +0 -120
  57. data/lib/beaker/answers/version28.rb +0 -121
  58. data/lib/beaker/answers/version30.rb +0 -227
  59. data/lib/beaker/answers/version32.rb +0 -44
  60. data/lib/beaker/answers/version34.rb +0 -51
  61. data/lib/beaker/answers/version38.rb +0 -29
  62. data/lib/beaker/answers/version40.rb +0 -44
  63. data/spec/beaker/answers_spec.rb +0 -547
@@ -328,6 +328,7 @@ module Beaker
328
328
  end
329
329
 
330
330
  normalize_and_validate_tags()
331
+ resolve_symlinks()
331
332
 
332
333
  #set the default role
333
334
  set_default_host!(@options[:HOSTS])
@@ -365,6 +366,17 @@ module Beaker
365
366
  end
366
367
  end
367
368
 
369
+ # resolves all file symlinks that require it.
370
+ #
371
+ # @note doing it here allows us to not need duplicate logic, which we
372
+ # would need if we were doing it in the parser (--hosts & --config)
373
+ #
374
+ # @return nil
375
+ # @api public
376
+ def resolve_symlinks()
377
+ @options[:hosts_file] = File.realpath(@options[:hosts_file]) if @options[:hosts_file]
378
+ end
379
+
368
380
  private
369
381
 
370
382
  # @api private
@@ -178,7 +178,6 @@ module Beaker
178
178
  :ssh => {
179
179
  :config => false,
180
180
  :paranoid => false,
181
- :timeout => 300,
182
181
  :auth_methods => ["publickey"],
183
182
  :port => 22,
184
183
  :forward_agent => true,
@@ -6,6 +6,7 @@ module Beaker
6
6
  class SshConnection
7
7
 
8
8
  attr_accessor :logger
9
+ attr_accessor :ip, :vmhostname, :hostname
9
10
 
10
11
  RETRYABLE_EXCEPTIONS = [
11
12
  SocketError,
@@ -21,41 +22,65 @@ module Beaker
21
22
  IOError,
22
23
  ]
23
24
 
24
- def initialize hostname, user = nil, ssh_opts = {}, options = {}
25
- @hostname = hostname
25
+ def initialize name_hash, user = nil, ssh_opts = {}, options = {}
26
+ @vmhostname = name_hash[:vmhostname]
27
+ @ip = name_hash[:ip]
28
+ @hostname = name_hash[:hostname]
26
29
  @user = user
27
30
  @ssh_opts = ssh_opts
28
31
  @logger = options[:logger]
29
32
  @options = options
30
33
  end
31
34
 
32
- def self.connect hostname, user = 'root', ssh_opts = {}, options = {}
33
- connection = new hostname, user, ssh_opts, options
35
+ def self.connect name_hash, user = 'root', ssh_opts = {}, options = {}
36
+ connection = new name_hash, user, ssh_opts, options
34
37
  connection.connect
35
38
  connection
36
39
  end
37
40
 
41
+ def connect_block host, user, ssh_opts
42
+ try = 1
43
+ last_wait = 2
44
+ wait = 3
45
+ begin
46
+ @logger.debug "Attempting ssh connection to #{host}, user: #{user}, opts: #{ssh_opts}"
47
+ Net::SSH.start(host, user, ssh_opts)
48
+ rescue *RETRYABLE_EXCEPTIONS => e
49
+ if try <= 8
50
+ @logger.warn "Try #{try} -- Host #{host} unreachable: #{e.class.name} - #{e.message}"
51
+ @logger.warn "Trying again in #{wait} seconds"
52
+ sleep wait
53
+ (last_wait, wait) = wait, last_wait + wait
54
+ try += 1
55
+ retry
56
+ else
57
+ @logger.warn "Failed to connect to #{host}, after #{try} attempts"
58
+ nil
59
+ end
60
+ end
61
+ end
62
+
38
63
  # connect to the host
39
64
  def connect
40
- try = 1
41
- last_wait = 0
42
- wait = 1
43
- @ssh ||= begin
44
- @logger.debug "Attempting ssh connection to #{@hostname}, user: #{@user}, opts: #{@ssh_opts}"
45
- Net::SSH.start(@hostname, @user, @ssh_opts)
46
- rescue *RETRYABLE_EXCEPTIONS => e
47
- if try <= 11
48
- @logger.warn "Try #{try} -- Host #{@hostname} unreachable: #{e.class.name} - #{e.message}"
49
- @logger.warn "Trying again in #{wait} seconds"
50
- sleep wait
51
- (last_wait, wait) = wait, last_wait + wait
52
- try += 1
53
- retry
54
- else
55
- @logger.error "Failed to connect to #{@hostname}"
56
- raise
57
- end
58
- end
65
+ #try three ways to connect to host (ip, vmhostname, hostname)
66
+ methods = []
67
+ if @ip
68
+ @ssh ||= connect_block(@ip, @user, @ssh_opts)
69
+ methods << "ip (#{@ip})"
70
+ end
71
+ if @vmhostname && !@ssh
72
+ @ssh ||= connect_block(@vmhostname, @user, @ssh_opts)
73
+ methods << "vmhostname (#{@vmhostname})"
74
+ end
75
+ if @hostname && !@ssh
76
+ @ssh ||= connect_block(@hostname, @user, @ssh_opts)
77
+ methods << "hostname (#{@hostname})"
78
+ end
79
+ if not @ssh
80
+ @logger.error "Failed to connect to #{@hostname}, attempted #{methods.join(', ')}"
81
+ raise RuntimeError, "Cannot connect to #{@hostname}"
82
+ end
83
+ @ssh
59
84
  end
60
85
 
61
86
  # closes this SshConnection
@@ -1,4 +1,4 @@
1
- [ 'host', 'answers', 'dsl' ].each do |lib|
1
+ [ 'host', 'dsl' ].each do |lib|
2
2
  require "beaker/#{lib}"
3
3
  end
4
4
 
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '2.18.3'
3
+ STRING = '2.19.0'
4
4
  end
5
5
  end
@@ -29,12 +29,21 @@ describe ClassMixedWithDSLHelpers do
29
29
 
30
30
  it "returns its second and third arguments concatenated." do
31
31
  create_files(['destdir/name'])
32
- result = subject.fetch_http_file "http://beaker.tool/", "name", "destdir"
32
+ result = subject.fetch_http_file "http://beaker.tool", "name", "destdir"
33
33
  expect(result).to eq("destdir/name")
34
34
  end
35
35
 
36
36
  end
37
37
 
38
+ describe 'given invalid arguments' do
39
+
40
+ it 'chomps correctly when given a URL ending with a / character' do
41
+ expect( subject ).to receive( :open ).with( 'http://beaker.tool/name', anything )
42
+ subject.fetch_http_file( "http://beaker.tool/", "name", "destdir" )
43
+ end
44
+
45
+ end
46
+
38
47
  end
39
48
 
40
49
  describe "#fetch_http_dir" do
@@ -16,10 +16,11 @@ end
16
16
  describe ClassMixedWithDSLInstallUtils do
17
17
  let(:metadata) { @metadata ||= {} }
18
18
  let(:presets) { Beaker::Options::Presets.new }
19
- let(:opts) { presets.presets.merge(presets.env_vars) }
19
+ let(:opts) { presets.presets.merge(presets.env_vars).merge({ :type => 'foss' }) }
20
20
  let(:basic_hosts) { make_hosts( { :pe_ver => '3.0',
21
- :platform => 'linux',
22
- :roles => [ 'agent' ] }, 4 ) }
21
+ :platform => 'linux',
22
+ :roles => [ 'agent' ],
23
+ :type => 'foss' }, 4 ) }
23
24
  let(:hosts) { basic_hosts[0][:roles] = ['master', 'database', 'dashboard']
24
25
  basic_hosts[1][:platform] = 'windows'
25
26
  basic_hosts[2][:platform] = 'osx-10.9-x86_64'
@@ -29,13 +30,16 @@ describe ClassMixedWithDSLInstallUtils do
29
30
  let(:winhost) { make_host( 'winhost', { :platform => 'windows',
30
31
  :pe_ver => '3.0',
31
32
  :working_dir => '/tmp',
33
+ :type => 'foss',
32
34
  :is_cygwin => true} ) }
33
35
  let(:winhost_non_cygwin) { make_host( 'winhost_non_cygwin', { :platform => 'windows',
34
36
  :pe_ver => '3.0',
35
37
  :working_dir => '/tmp',
38
+ :type => 'foss',
36
39
  :is_cygwin => 'false' } ) }
37
40
  let(:machost) { make_host( 'machost', { :platform => 'osx-10.9-x86_64',
38
41
  :pe_ver => '3.0',
42
+ :type => 'foss',
39
43
  :working_dir => '/tmp' } ) }
40
44
  let(:freebsdhost9) { make_host( 'freebsdhost9', { :platform => 'freebsd-9-x64',
41
45
  :pe_ver => '3.0',
@@ -46,55 +50,60 @@ describe ClassMixedWithDSLInstallUtils do
46
50
  let(:unixhost) { make_host( 'unixhost', { :platform => 'linux',
47
51
  :pe_ver => '3.0',
48
52
  :working_dir => '/tmp',
53
+ :type => 'foss',
49
54
  :dist => 'puppet-enterprise-3.1.0-rc0-230-g36c9e5c-debian-7-i386' } ) }
50
55
  let(:eoshost) { make_host( 'eoshost', { :platform => 'eos',
51
56
  :pe_ver => '3.0',
52
57
  :working_dir => '/tmp',
58
+ :type => 'foss',
53
59
  :dist => 'puppet-enterprise-3.7.1-rc0-78-gffc958f-eos-4-i386' } ) }
60
+ let(:win_temp) { 'C:\\Windows\\Temp' }
54
61
 
55
62
 
56
63
  context '#configure_foss_defaults_on' do
57
- it 'uses aio paths for hosts of type aio' do
64
+ it 'uses aio paths for hosts with role aio' do
58
65
  hosts.each do |host|
59
- host[:type] = 'aio'
66
+ host[:pe_ver] = nil
67
+ host[:version] = nil
68
+ host[:roles] = host[:roles] | ['aio']
60
69
  end
70
+ expect(subject).to receive(:add_foss_defaults_on).exactly(hosts.length).times
61
71
  expect(subject).to receive(:add_aio_defaults_on).exactly(hosts.length).times
62
72
  expect(subject).to receive(:add_puppet_paths_on).exactly(hosts.length).times
63
73
 
64
74
  subject.configure_foss_defaults_on( hosts )
65
75
  end
66
76
 
67
- it 'uses foss paths for hosts of type foss' do
77
+ it 'uses no paths for hosts with no type' do
68
78
  hosts.each do |host|
69
- host[:type] = 'foss'
79
+ host[:type] = nil
70
80
  end
71
- expect(subject).to receive(:add_foss_defaults_on).exactly(hosts.length).times
72
- expect(subject).to receive(:add_puppet_paths_on).exactly(hosts.length).times
81
+ expect(subject).to receive(:add_aio_defaults_on).never
82
+ expect(subject).to receive(:add_foss_defaults_on).never
83
+ expect(subject).to receive(:add_puppet_paths_on).never
73
84
 
74
85
  subject.configure_foss_defaults_on( hosts )
75
86
  end
76
87
 
77
- it 'uses foss paths for hosts with no type and version < 4.0' do
78
- expect(subject).to receive(:add_foss_defaults_on).exactly(hosts.length).times
88
+ it 'uses aio paths for hosts with aio type (backwards compatability)' do
89
+ hosts.each do |host|
90
+ host[:type] = 'aio'
91
+ end
92
+ expect(subject).to receive(:add_aio_defaults_on).exactly(hosts.length).times
93
+ expect(subject).to receive(:add_foss_defaults_on).never
79
94
  expect(subject).to receive(:add_puppet_paths_on).exactly(hosts.length).times
80
95
 
81
96
  subject.configure_foss_defaults_on( hosts )
82
97
  end
83
98
 
84
- it 'uses aio paths for hosts of version >= 4.0, except for master/database/dashboard' do
85
- agents = []
86
- not_agents = []
99
+ it 'uses aio paths for hosts of version >= 4.0' do
87
100
  hosts.each do |host|
88
101
  host[:version] = '4.0'
89
102
  host[:pe_ver] = nil
90
- if subject.agent_only(host)
91
- agents << host
92
- else
93
- not_agents << host
94
- end
103
+ host[:roles] = host[:roles] - ['aio']
95
104
  end
96
- expect(subject).to receive(:add_aio_defaults_on).exactly(agents.length).times
97
- expect(subject).to receive(:add_foss_defaults_on).exactly(not_agents.length).times
105
+ expect(subject).to receive(:add_aio_defaults_on).exactly(hosts.length).times
106
+ expect(subject).to receive(:add_foss_defaults_on).exactly(hosts.length).times
98
107
  expect(subject).to receive(:add_puppet_paths_on).exactly(hosts.length).times
99
108
 
100
109
  subject.configure_foss_defaults_on( hosts )
@@ -103,8 +112,23 @@ describe ClassMixedWithDSLInstallUtils do
103
112
  it 'uses foss paths for hosts of version < 4.0' do
104
113
  hosts.each do |host|
105
114
  host[:version] = '3.8'
115
+ host[:pe_ver] = nil
116
+ end
117
+ expect(subject).to receive(:add_foss_defaults_on).exactly(hosts.length).times
118
+ expect(subject).to receive(:add_aio_defaults_on).never
119
+ expect(subject).to receive(:add_puppet_paths_on).exactly(hosts.length).times
120
+
121
+ subject.configure_foss_defaults_on( hosts )
122
+ end
123
+
124
+ it 'uses foss paths for foss-like type foss-package' do
125
+ hosts.each do |host|
126
+ host[:type] = 'foss-package'
127
+ host[:version] = '3.8'
128
+ host[:pe_ver] = nil
106
129
  end
107
130
  expect(subject).to receive(:add_foss_defaults_on).exactly(hosts.length).times
131
+ expect(subject).to receive(:add_aio_defaults_on).never
108
132
  expect(subject).to receive(:add_puppet_paths_on).exactly(hosts.length).times
109
133
 
110
134
  subject.configure_foss_defaults_on( hosts )
@@ -112,6 +136,54 @@ describe ClassMixedWithDSLInstallUtils do
112
136
 
113
137
  end
114
138
 
139
+ context 'lookup_in_env' do
140
+ it 'returns a default properly' do
141
+ env_var = subject.lookup_in_env('noway', 'nonesuch', 'returnme')
142
+ expect(env_var).to be == 'returnme'
143
+ env_var = subject.lookup_in_env('noway', nil, 'returnme')
144
+ expect(env_var).to be == 'returnme'
145
+ end
146
+ it 'finds correct env variable' do
147
+ allow(ENV).to receive(:[]).with(nil).and_return(nil)
148
+ allow(ENV).to receive(:[]).with('REALLYNONE').and_return(nil)
149
+ allow(ENV).to receive(:[]).with('NONESUCH').and_return('present')
150
+ allow(ENV).to receive(:[]).with('NOWAY_PROJ_NONESUCH').and_return('exists')
151
+ env_var = subject.lookup_in_env('nonesuch', 'noway-proj', 'fail')
152
+ expect(env_var).to be == 'exists'
153
+ env_var = subject.lookup_in_env('nonesuch')
154
+ expect(env_var).to be == 'present'
155
+ env_var = subject.lookup_in_env('reallynone')
156
+ expect(env_var).to be == nil
157
+ env_var = subject.lookup_in_env('reallynone',nil,'default')
158
+ expect(env_var).to be == 'default'
159
+ end
160
+ end
161
+
162
+ context 'build_giturl' do
163
+ it 'returns urls properly' do
164
+ allow(ENV).to receive(:[]).with('SERVER').and_return(nil)
165
+ allow(ENV).to receive(:[]).with('FORK').and_return(nil)
166
+ allow(ENV).to receive(:[]).with('PUPPET_FORK').and_return(nil)
167
+ allow(ENV).to receive(:[]).with('PUPPET_SERVER').and_return(nil)
168
+ url = subject.build_giturl('puppet')
169
+ expect(url).to be == 'https://github.com/puppetlabs/puppet.git'
170
+ url = subject.build_giturl('puppet', 'er0ck')
171
+ expect(url).to be == 'https://github.com/er0ck/puppet.git'
172
+ url = subject.build_giturl('puppet', 'er0ck', 'bitbucket.com')
173
+ expect(url).to be == 'https://bitbucket.com/er0ck-puppet.git'
174
+ url = subject.build_giturl('puppet', 'er0ck', 'github.com', 'https://')
175
+ expect(url).to be == 'https://github.com/er0ck/puppet.git'
176
+ url = subject.build_giturl('puppet', 'er0ck', 'github.com', 'https')
177
+ expect(url).to be == 'https://github.com/er0ck/puppet.git'
178
+ url = subject.build_giturl('puppet', 'er0ck', 'github.com', 'git@')
179
+ expect(url).to be == 'git@github.com:er0ck/puppet.git'
180
+ url = subject.build_giturl('puppet', 'er0ck', 'github.com', 'git')
181
+ expect(url).to be == 'git@github.com:er0ck/puppet.git'
182
+ url = subject.build_giturl('puppet', 'er0ck', 'github.com', 'ssh')
183
+ expect(url).to be == 'git@github.com:er0ck/puppet.git'
184
+ end
185
+ end
186
+
115
187
  context 'extract_repo_info_from' do
116
188
  [{ :protocol => 'git', :path => 'git://github.com/puppetlabs/project.git' },
117
189
  { :protocol => 'ssh', :path => 'git@github.com:puppetlabs/project.git' },
@@ -175,13 +247,15 @@ describe ClassMixedWithDSLInstallUtils do
175
247
  end
176
248
 
177
249
  context 'install_puppet_from_msi' do
250
+ before :each do
251
+ expect(subject).to receive(:get_temp_path).and_return(win_temp)
252
+ end
178
253
 
179
254
  it 'installs puppet on cygwin windows' do
180
255
  allow(subject).to receive(:link_exists?).and_return( true )
181
-
182
- expect(subject).to receive(:on).with(winhost, 'curl -O http://downloads.puppetlabs.com/windows/puppet-3.7.1.msi')
256
+ expect(subject).to receive(:on).with(winhost, "curl -o \"#{win_temp}\\puppet-3.7.1.msi\" -O http://downloads.puppetlabs.com/windows/puppet-3.7.1.msi")
183
257
  expect(subject).to receive(:on).with(winhost, " echo 'export PATH=$PATH:\"/cygdrive/c/Program Files (x86)/Puppet Labs/Puppet/bin\":\"/cygdrive/c/Program Files/Puppet Labs/Puppet/bin\"' > /etc/bash.bashrc ")
184
- expect(subject).to receive(:on).with(winhost, 'cmd /C \'start /w msiexec.exe /qn /i puppet-3.7.1.msi\'')
258
+ expect(subject).to receive(:install_msi_on).with(winhost, "#{win_temp}\\puppet-3.7.1.msi", {}, {:debug => nil})
185
259
 
186
260
  subject.install_puppet_from_msi( winhost, {:version => '3.7.1', :win_download_url => 'http://downloads.puppetlabs.com/windows'} )
187
261
  end
@@ -191,18 +265,18 @@ describe ClassMixedWithDSLInstallUtils do
191
265
 
192
266
  expect(winhost_non_cygwin).to receive(:mkdir_p).with('C:\\ProgramData\\PuppetLabs\\puppet\\etc\\modules')
193
267
 
194
- expect(subject).to receive(:on) do |winhost_non_cygwin, beaker_command|
268
+ expect(subject).to receive(:on).with(winhost_non_cygwin, instance_of( Beaker::Command )) do |host, beaker_command|
195
269
  expect(beaker_command.command).to eq('powershell.exe')
196
- expect(beaker_command.args).to eq(["-ExecutionPolicy Bypass", "-InputFormat None", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command $webclient = New-Object System.Net.WebClient; $webclient.DownloadFile('http://downloads.puppetlabs.com/windows/puppet-3.7.1.msi','C:\\Windows\\Temp\\puppet-3.7.1.msi')"])
197
- end
270
+ expect(beaker_command.args).to eq(["-ExecutionPolicy Bypass", "-InputFormat None", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command $webclient = New-Object System.Net.WebClient; $webclient.DownloadFile('http://downloads.puppetlabs.com/windows/puppet-3.7.1.msi','#{win_temp}\\puppet-3.7.1.msi')"])
271
+ end.once
198
272
 
199
- expect(subject).to receive(:on).with(winhost_non_cygwin, "start /w msiexec.exe /qn /i C:\\Windows\\Temp\\puppet-3.7.1.msi")
273
+ expect(subject).to receive(:install_msi_on).with(winhost_non_cygwin, "#{win_temp}\\puppet-3.7.1.msi", {}, {:debug => nil})
200
274
 
201
275
  subject.install_puppet_from_msi( winhost_non_cygwin, {:version => '3.7.1', :win_download_url => 'http://downloads.puppetlabs.com/windows'} )
202
276
  end
203
277
  end
204
278
 
205
- context 'install_from_git' do
279
+ context 'clone_git_repo_on' do
206
280
  it 'does a ton of stuff it probably shouldnt' do
207
281
  repo = { :name => 'puppet',
208
282
  :path => 'git://my.server.net/puppet.git',
@@ -214,11 +288,11 @@ describe ClassMixedWithDSLInstallUtils do
214
288
  allow( subject ).to receive( :metadata ).and_return( metadata )
215
289
  allow( subject ).to receive( :configure_foss_defaults_on ).and_return( true )
216
290
 
217
- expect( subject ).to receive( :logger ).exactly( 3 ).times.and_return( logger )
218
- expect( subject ).to receive( :on ).exactly( 4 ).times
291
+ expect( subject ).to receive( :logger ).exactly( 2 ).times.and_return( logger )
292
+ expect( subject ).to receive( :on ).exactly( 3 ).times
219
293
 
220
294
  subject.instance_variable_set( :@metadata, {} )
221
- subject.install_from_git( host, path, repo )
295
+ subject.clone_git_repo_on( host, path, repo )
222
296
  end
223
297
 
224
298
  it 'allows a checkout depth of 1' do
@@ -233,15 +307,14 @@ describe ClassMixedWithDSLInstallUtils do
233
307
  logger = double.as_null_object
234
308
  allow( subject ).to receive( :metadata ).and_return( metadata )
235
309
  allow( subject ).to receive( :configure_foss_defaults_on ).and_return( true )
236
- expect( subject ).to receive( :logger ).exactly( 3 ).times.and_return( logger )
237
- expect( subject ).to receive( :on ).with( host,"test -d #{path} || mkdir -p #{path}").exactly( 1 ).times
310
+ expect( subject ).to receive( :logger ).exactly( 2 ).times.and_return( logger )
311
+ expect( subject ).to receive( :on ).with( host, "test -d #{path} || mkdir -p #{path}", {:accept_all_exit_codes=>true} ).exactly( 1 ).times
238
312
  # this is the the command we want to test
239
- expect( subject ).to receive( :on ).with( host, cmd ).exactly( 1 ).times
240
- expect( subject ).to receive( :on ).with( host, "cd #{path}/#{repo[:name]} && git remote rm origin && git remote add origin #{repo[:path]} && git fetch origin +refs/pull/*:refs/remotes/origin/pr/* +refs/heads/*:refs/remotes/origin/* && git clean -fdx && git checkout -f #{repo[:rev]}" ).exactly( 1 ).times
241
- expect( subject ).to receive( :on ).with( host, "cd #{path}/#{repo[:name]} && if [ -f install.rb ]; then ruby ./install.rb ; else true; fi" ).exactly( 1 ).times
313
+ expect( subject ).to receive( :on ).with( host, cmd, {:accept_all_exit_codes=>true} ).exactly( 1 ).times
314
+ expect( subject ).to receive( :on ).with( host, "cd #{path}/#{repo[:name]} && git remote rm origin && git remote add origin #{repo[:path]} && git fetch origin +refs/pull/*:refs/remotes/origin/pr/* +refs/heads/*:refs/remotes/origin/* && git clean -fdx && git checkout -f #{repo[:rev]}", {:accept_all_exit_codes=>true} ).exactly( 1 ).times
242
315
 
243
316
  subject.instance_variable_set( :@metadata, {} )
244
- subject.install_from_git( host, path, repo )
317
+ subject.clone_git_repo_on( host, path, repo )
245
318
  end
246
319
 
247
320
  it 'allows a checkout depth with a rev from a specific branch' do
@@ -257,16 +330,57 @@ describe ClassMixedWithDSLInstallUtils do
257
330
  allow( subject ).to receive( :configure_foss_defaults_on ).and_return( true )
258
331
  logger = double.as_null_object
259
332
  allow( subject ).to receive( :metadata ).and_return( metadata )
260
- expect( subject ).to receive( :logger ).exactly( 3 ).times.and_return( logger )
261
- expect( subject ).to receive( :on ).with( host,"test -d #{path} || mkdir -p #{path}").exactly( 1 ).times
333
+ expect( subject ).to receive( :logger ).exactly( 2 ).times.and_return( logger )
334
+ expect( subject ).to receive( :on ).with( host, "test -d #{path} || mkdir -p #{path}", {:accept_all_exit_codes=>true} ).exactly( 1 ).times
262
335
  # this is the the command we want to test
263
- expect( subject ).to receive( :on ).with( host, cmd ).exactly( 1 ).times
264
- expect( subject ).to receive( :on ).with( host, "cd #{path}/#{repo[:name]} && git remote rm origin && git remote add origin #{repo[:path]} && git fetch origin +refs/pull/*:refs/remotes/origin/pr/* +refs/heads/*:refs/remotes/origin/* && git clean -fdx && git checkout -f #{repo[:rev]}" ).exactly( 1 ).times
265
- expect( subject ).to receive( :on ).with( host, "cd #{path}/#{repo[:name]} && if [ -f install.rb ]; then ruby ./install.rb ; else true; fi" ).exactly( 1 ).times
336
+ expect( subject ).to receive( :on ).with( host, cmd, {:accept_all_exit_codes=>true} ).exactly( 1 ).times
337
+ expect( subject ).to receive( :on ).with( host, "cd #{path}/#{repo[:name]} && git remote rm origin && git remote add origin #{repo[:path]} && git fetch origin +refs/pull/*:refs/remotes/origin/pr/* +refs/heads/*:refs/remotes/origin/* && git clean -fdx && git checkout -f #{repo[:rev]}", {:accept_all_exit_codes=>true} ).exactly( 1 ).times
338
+
339
+ subject.instance_variable_set( :@metadata, {} )
340
+ subject.clone_git_repo_on( host, path, repo )
341
+ end
342
+ end
343
+
344
+ context 'install_from_git' do
345
+ it 'does a ton of stuff it probably shouldnt' do
346
+ repo = { :name => 'puppet',
347
+ :path => 'git://my.server.net/puppet.git',
348
+ :rev => 'master' }
349
+ path = '/path/to/repos'
350
+ host = { 'platform' => 'debian' }
351
+ logger = double.as_null_object
352
+
353
+ allow( subject ).to receive( :metadata ).and_return( metadata )
354
+ allow( subject ).to receive( :configure_foss_defaults_on ).and_return( true )
355
+
356
+ expect( subject ).to receive( :logger ).exactly( 3 ).times.and_return( logger )
357
+ expect( subject ).to receive( :on ).exactly( 4 ).times
266
358
 
267
359
  subject.instance_variable_set( :@metadata, {} )
268
360
  subject.install_from_git( host, path, repo )
269
361
  end
362
+
363
+ it 'should attempt to install ruby code' do
364
+ repo = { :name => 'puppet',
365
+ :path => 'git://my.server.net/puppet.git',
366
+ :rev => 'master',
367
+ :depth => 1 }
368
+
369
+ path = '/path/to/repos'
370
+ cmd = "test -d #{path}/#{repo[:name]} || git clone --branch #{repo[:rev]} --depth #{repo[:depth]} #{repo[:path]} #{path}/#{repo[:name]}"
371
+ host = { 'platform' => 'debian' }
372
+ logger = double.as_null_object
373
+ allow( subject ).to receive( :metadata ).and_return( metadata )
374
+ allow( subject ).to receive( :configure_foss_defaults_on ).and_return( true )
375
+ expect( subject ).to receive( :logger ).exactly( 3 ).times.and_return( logger )
376
+ expect( subject ).to receive( :on ).with( host, "test -d #{path} || mkdir -p #{path}", {:accept_all_exit_codes=>true} ).exactly( 1 ).times
377
+ expect( subject ).to receive( :on ).with( host, cmd, {:accept_all_exit_codes=>true} ).exactly( 1 ).times
378
+ expect( subject ).to receive( :on ).with( host, "cd #{path}/#{repo[:name]} && git remote rm origin && git remote add origin #{repo[:path]} && git fetch origin +refs/pull/*:refs/remotes/origin/pr/* +refs/heads/*:refs/remotes/origin/* && git clean -fdx && git checkout -f #{repo[:rev]}", {:accept_all_exit_codes=>true} ).exactly( 1 ).times
379
+ expect( subject ).to receive( :on ).with( host, "cd #{path}/#{repo[:name]} && if [ -f install.rb ]; then ruby ./install.rb ; else true; fi", {:accept_all_exit_codes=>true} ).exactly( 1 ).times
380
+
381
+ subject.instance_variable_set( :@metadata, {} )
382
+ subject.install_from_git_on( host, path, repo )
383
+ end
270
384
  end
271
385
 
272
386
  describe '#install_puppet' do
@@ -337,19 +451,28 @@ describe ClassMixedWithDSLInstallUtils do
337
451
  end
338
452
  context 'on windows' do
339
453
  let(:platform) { Beaker::Platform.new('windows-2008r2-i386') }
454
+
455
+ before :each do
456
+ expect(subject).to receive(:get_temp_path).exactly(hosts.length).times.and_return(win_temp)
457
+ end
458
+
340
459
  it 'installs specific version of puppet when passed :version' do
341
460
  allow(hosts[0]).to receive(:is_cygwin?).and_return(true)
342
461
  allow(subject).to receive(:link_exists?).and_return( true )
343
- expect(subject).to receive(:on).with(hosts[0], 'curl -O http://downloads.puppetlabs.com/windows/puppet-3.msi')
462
+ expect(subject).to receive(:on).with(hosts[0], "curl -o \"#{win_temp}\\puppet-3.msi\" -O http://downloads.puppetlabs.com/windows/puppet-3.msi")
344
463
  expect(subject).to receive(:on).with(hosts[0], " echo 'export PATH=$PATH:\"/cygdrive/c/Program Files (x86)/Puppet Labs/Puppet/bin\":\"/cygdrive/c/Program Files/Puppet Labs/Puppet/bin\"' > /etc/bash.bashrc ")
345
- expect(subject).to receive(:on).with(hosts[0], 'cmd /C \'start /w msiexec.exe /qn /i puppet-3.msi\'')
464
+ expect(subject).to receive(:install_msi_on).with(hosts[0], "#{win_temp}\\puppet-3.msi", {}, {:debug => nil}).exactly(1).times
465
+ allow(subject).to receive(:install_msi_on).with(any_args)
466
+
346
467
  subject.install_puppet(:version => '3')
347
468
  end
348
469
  it 'installs from custom url when passed :win_download_url' do
349
470
  allow(hosts[0]).to receive(:is_cygwin?).and_return(true)
350
471
  allow(subject).to receive(:link_exists?).and_return( true )
351
- expect(subject).to receive(:on).with(hosts[0], 'curl -O http://nightlies.puppetlabs.com/puppet-latest/repos/windows/puppet-3.msi')
352
- expect(subject).to receive(:on).with(hosts[0], 'cmd /C \'start /w msiexec.exe /qn /i puppet-3.msi\'')
472
+ expect(subject).to receive(:on).with(hosts[0], "curl -o \"#{win_temp}\\puppet-3.msi\" -O http://nightlies.puppetlabs.com/puppet-latest/repos/windows/puppet-3.msi")
473
+ expect(subject).to receive(:install_msi_on).with(hosts[0], "#{win_temp}\\puppet-3.msi", {}, {:debug => nil})
474
+ allow(subject).to receive(:install_msi_on).with(any_args)
475
+
353
476
  subject.install_puppet( :version => '3', :win_download_url => 'http://nightlies.puppetlabs.com/puppet-latest/repos/windows' )
354
477
  end
355
478
  end
@@ -742,13 +865,14 @@ describe ClassMixedWithDSLInstallUtils do
742
865
  host['platform'] = platform
743
866
  opts = { :version => '0.1.0' }
744
867
  allow( subject ).to receive( :options ).and_return( {} )
868
+ copied_path = "#{win_temp}\\puppet-agent-x64.msi"
745
869
  mock_echo = Object.new()
746
- allow( mock_echo ).to receive( :raw_output ).and_return( " " )
870
+ allow( mock_echo ).to receive( :raw_output ).and_return( copied_path )
747
871
 
748
872
  expect(subject).to receive(:fetch_http_file).once.with(/\/windows$/, 'puppet-agent-x64.msi', /\/windows$/)
749
873
  expect(subject).to receive(:scp_to).once.with(host, /\/puppet-agent-x64.msi$/, /cygpath/)
874
+ expect(subject).to receive(:install_msi_on).with(host, copied_path, {}, {:debug => nil}).once
750
875
  expect(subject).to receive(:on).ordered.with(host, /echo/).and_return(mock_echo)
751
- expect(subject).to receive(:on).ordered.with(host, anything)
752
876
 
753
877
  subject.install_puppetagent_dev_repo( host, opts )
754
878
  end
@@ -786,6 +910,25 @@ describe ClassMixedWithDSLInstallUtils do
786
910
  end
787
911
  end
788
912
 
913
+ describe '#install_puppet_agent_pe_promoted_repo_on' do
914
+
915
+ it 'splits the platform string version correctly to get ubuntu puppet-agent packages' do
916
+ platform = Object.new()
917
+ allow(platform).to receive(:to_array) { ['ubuntu', '9999', 'x42']}
918
+ host = basic_hosts.first
919
+ host['platform'] = platform
920
+
921
+ expect(subject).to receive(:fetch_http_file).once.with(/\/puppet-agent\//, "puppet-agent-ubuntu-99.99-x42.tar.gz", /ubuntu/)
922
+ expect(subject).to receive(:scp_to).once.with(host, /-ubuntu-99.99-x42\./, "/root")
923
+ expect(subject).to receive(:on).ordered.with(host, /^tar.*-ubuntu-99.99-x42/)
924
+ expect(subject).to receive(:on).ordered.with(host, /dpkg\ -i\ --force-all/)
925
+ expect(subject).to receive(:on).ordered.with(host, /apt-get\ update/)
926
+
927
+ subject.install_puppet_agent_pe_promoted_repo_on( host, {} )
928
+ end
929
+
930
+ end
931
+
789
932
  describe '#install_cert_on_windows' do
790
933
  before do
791
934
  allow(subject).to receive(:on).and_return(Beaker::Result.new({},''))
@@ -842,11 +985,13 @@ describe ClassMixedWithDSLInstallUtils do
842
985
 
843
986
  before :each do
844
987
  allow( subject ).to receive( :configure_foss_defaults_on ).and_return( true )
988
+ allow( subject ).to receive( :install_msi_on ).with( any_args )
845
989
  end
846
990
 
847
991
  def test_fetch_http_file_no_ending_slash(platform)
848
992
  @platform = platform
849
993
  allow( subject ).to receive( :scp_to )
994
+ allow( subject ).to receive( :configure_type_defaults_on ).with(host)
850
995
 
851
996
  expect( subject ).to receive( :fetch_http_file ).with( /[^\/]\z/, anything, anything )
852
997
  subject.install_puppet_agent_pe_promoted_repo_on( host, opts )