beaker-puppet 0.17.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +21 -0
- data/acceptance/pre_suite/gem/install.rb +2 -0
- data/acceptance/pre_suite/git/install.rb +2 -6
- data/acceptance/pre_suite/pkg/install.rb +2 -0
- data/acceptance/tests/README.md +2 -0
- data/acceptance/tests/clone_git_repo_on_test.rb +43 -0
- data/acceptance/tests/create_tmpdir_on_test.rb +47 -0
- data/acceptance/tests/install_smoke_test.rb +2 -0
- data/acceptance/tests/stub_host.rb +2 -0
- data/acceptance/tests/web_helpers_test.rb +2 -0
- data/acceptance/tests/with_puppet_running_on.rb +2 -0
- data/beaker-puppet.gemspec +3 -0
- data/lib/beaker-puppet.rb +14 -25
- data/lib/beaker-puppet/helpers/puppet_helpers.rb +49 -0
- data/lib/beaker-puppet/install_utils/foss_utils.rb +2 -1
- data/lib/beaker-puppet/install_utils/puppet5.rb +185 -183
- data/lib/beaker-puppet/install_utils/windows_utils.rb +223 -0
- data/lib/beaker-puppet/version.rb +1 -1
- data/spec/beaker-puppet/helpers/facter_helpers_spec.rb +1 -1
- data/spec/beaker-puppet/helpers/puppet_helpers_spec.rb +92 -2
- data/spec/beaker-puppet/helpers/tk_helpers_spec.rb +1 -3
- data/spec/beaker-puppet/install_utils/ezbake_utils_spec.rb +279 -0
- data/spec/beaker-puppet/install_utils/module_utils_spec.rb +2 -0
- data/spec/beaker-puppet/install_utils/puppet5_spec.rb +1 -1
- data/spec/beaker-puppet/install_utils/windows_utils_spec.rb +263 -0
- data/spec/beaker-puppet/wrappers_spec.rb +34 -0
- metadata +22 -3
- data/acceptance/lib/beaker/acceptance/install_utils.rb +0 -58
@@ -0,0 +1,223 @@
|
|
1
|
+
module Beaker
|
2
|
+
module DSL
|
3
|
+
module InstallUtils
|
4
|
+
#
|
5
|
+
# This module contains methods useful for Windows installs
|
6
|
+
#
|
7
|
+
module WindowsUtils
|
8
|
+
# Given a host, returns it's system TEMP path
|
9
|
+
#
|
10
|
+
# @param [Host] host An object implementing {Beaker::Hosts}'s interface.
|
11
|
+
#
|
12
|
+
# @return [String] system temp path
|
13
|
+
def get_system_temp_path(host)
|
14
|
+
host.system_temp_path
|
15
|
+
end
|
16
|
+
alias_method :get_temp_path, :get_system_temp_path
|
17
|
+
|
18
|
+
# Generates commands to be inserted into a Windows batch file to launch an MSI install
|
19
|
+
# @param [String] msi_path The path of the MSI - can be a local Windows style file path like
|
20
|
+
# c:\temp\puppet.msi OR a url like https://download.com/puppet.msi or file://c:\temp\puppet.msi
|
21
|
+
# @param [Hash{String=>String}] msi_opts MSI installer options
|
22
|
+
# See https://docs.puppetlabs.com/guides/install_puppet/install_windows.html#msi-properties
|
23
|
+
# @param [String] log_path The path to write the MSI log - must be a local Windows style file path
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
def msi_install_script(msi_path, msi_opts, log_path)
|
27
|
+
# msiexec requires backslashes in file paths launched under cmd.exe start /w
|
28
|
+
url_pattern = /^(https?|file):\/\//
|
29
|
+
msi_path = msi_path.gsub(/\//, "\\") if msi_path !~ url_pattern
|
30
|
+
|
31
|
+
msi_params = msi_opts.map{|k, v| "#{k}=#{v}"}.join(' ')
|
32
|
+
|
33
|
+
# msiexec requires quotes around paths with backslashes - c:\ or file://c:\
|
34
|
+
# not strictly needed for http:// but it simplifies this code
|
35
|
+
batch_contents = <<-BATCH
|
36
|
+
start /w msiexec.exe /i \"#{msi_path}\" /qn /L*V #{log_path} #{msi_params}
|
37
|
+
exit /B %errorlevel%
|
38
|
+
BATCH
|
39
|
+
end
|
40
|
+
|
41
|
+
# Given a host, path to MSI and MSI options, will create a batch file
|
42
|
+
# on the host, returning the path to the randomized batch file and
|
43
|
+
# the randomized log file
|
44
|
+
#
|
45
|
+
# @param [Host] host An object implementing {Beaker::Hosts}'s interface.
|
46
|
+
# @param [String] msi_path The path of the MSI - can be a local Windows
|
47
|
+
# style file path like c:\temp\puppet.msi OR a url like
|
48
|
+
# https://download.com/puppet.msi or file://c:\temp\puppet.msi
|
49
|
+
# @param [Hash{String=>String}] msi_opts MSI installer options
|
50
|
+
# See https://docs.puppetlabs.com/guides/install_puppet/install_windows.html#msi-properties
|
51
|
+
#
|
52
|
+
# @api private
|
53
|
+
# @return [String, String] path to the batch file, patch to the log file
|
54
|
+
def create_install_msi_batch_on(host, msi_path, msi_opts)
|
55
|
+
timestamp = Time.new.strftime('%Y-%m-%d_%H.%M.%S')
|
56
|
+
tmp_path = host.system_temp_path
|
57
|
+
tmp_path.gsub!('/', '\\')
|
58
|
+
|
59
|
+
batch_name = "install-puppet-msi-#{timestamp}.bat"
|
60
|
+
batch_path = "#{tmp_path}#{host.scp_separator}#{batch_name}"
|
61
|
+
log_path = "#{tmp_path}\\install-puppet-#{timestamp}.log"
|
62
|
+
|
63
|
+
Tempfile.open(batch_name) do |tmp_file|
|
64
|
+
batch_contents = msi_install_script(msi_path, msi_opts, log_path)
|
65
|
+
|
66
|
+
File.open(tmp_file.path, 'w') { |file| file.puts(batch_contents) }
|
67
|
+
host.do_scp_to(tmp_file.path, batch_path, {})
|
68
|
+
end
|
69
|
+
|
70
|
+
return batch_path, log_path
|
71
|
+
end
|
72
|
+
|
73
|
+
# Given hosts construct a PATH that includes puppetbindir, facterbindir and hierabindir
|
74
|
+
# @param [Host, Array<Host>, String, Symbol] hosts One or more hosts to act upon,
|
75
|
+
# or a role (String or Symbol) that identifies one or more hosts.
|
76
|
+
# @param [String] msi_path The path of the MSI - can be a local Windows style file path like
|
77
|
+
# c:\temp\puppet.msi OR a url like https://download.com/puppet.msi or file://c:\temp\puppet.msi
|
78
|
+
# @param [Hash{String=>String}] msi_opts MSI installer options
|
79
|
+
# See https://docs.puppetlabs.com/guides/install_puppet/install_windows.html#msi-properties
|
80
|
+
# @option msi_opts [String] INSTALLIDIR Where Puppet and its dependencies should be installed.
|
81
|
+
# (Defaults vary based on operating system and intaller architecture)
|
82
|
+
# Requires Puppet 2.7.12 / PE 2.5.0
|
83
|
+
# @option msi_opts [String] PUPPET_MASTER_SERVER The hostname where the puppet master server can be reached.
|
84
|
+
# (Defaults to puppet)
|
85
|
+
# Requires Puppet 2.7.12 / PE 2.5.0
|
86
|
+
# @option msi_opts [String] PUPPET_CA_SERVER The hostname where the CA puppet master server can be reached, if you are using multiple masters and only one of them is acting as the CA.
|
87
|
+
# (Defaults the value of PUPPET_MASTER_SERVER)
|
88
|
+
# Requires Puppet 2.7.12 / PE 2.5.0
|
89
|
+
# @option msi_opts [String] PUPPET_AGENT_CERTNAME The node’s certificate name, and the name it uses when requesting catalogs. This will set a value for
|
90
|
+
# (Defaults to the node's fqdn as discovered by facter fqdn)
|
91
|
+
# Requires Puppet 2.7.12 / PE 2.5.0
|
92
|
+
# @option msi_opts [String] PUPPET_AGENT_ENVIRONMENT The node’s environment.
|
93
|
+
# (Defaults to production)
|
94
|
+
# Requires Puppet 3.3.1 / PE 3.1.0
|
95
|
+
# @option msi_opts [String] PUPPET_AGENT_STARTUP_MODE Whether the puppet agent service should run (or be allowed to run)
|
96
|
+
# (Defaults to Manual - valid values are Automatic, Manual or Disabled)
|
97
|
+
# Requires Puppet 3.4.0 / PE 3.2.0
|
98
|
+
# @option msi_opts [String] PUPPET_AGENT_ACCOUNT_USER Whether the puppet agent service should run (or be allowed to run)
|
99
|
+
# (Defaults to LocalSystem)
|
100
|
+
# Requires Puppet 3.4.0 / PE 3.2.0
|
101
|
+
# @option msi_opts [String] PUPPET_AGENT_ACCOUNT_PASSWORD The password to use for puppet agent’s user account
|
102
|
+
# (No default)
|
103
|
+
# Requires Puppet 3.4.0 / PE 3.2.0
|
104
|
+
# @option msi_opts [String] PUPPET_AGENT_ACCOUNT_DOMAIN The domain of puppet agent’s user account.
|
105
|
+
# (Defaults to .)
|
106
|
+
# Requires Puppet 3.4.0 / PE 3.2.0
|
107
|
+
# @option opts [Boolean] :debug output the MSI installation log when set to true
|
108
|
+
# otherwise do not output log (false; default behavior)
|
109
|
+
#
|
110
|
+
# @example
|
111
|
+
# install_msi_on(hosts, 'c:\puppet.msi', {:debug => true})
|
112
|
+
#
|
113
|
+
# @api private
|
114
|
+
def install_msi_on(hosts, msi_path, msi_opts = {}, opts = {})
|
115
|
+
block_on hosts do | host |
|
116
|
+
msi_opts['PUPPET_AGENT_STARTUP_MODE'] ||= 'Manual'
|
117
|
+
batch_path, log_file = create_install_msi_batch_on(host, msi_path, msi_opts)
|
118
|
+
|
119
|
+
# begin / rescue here so that we can reuse existing error msg propagation
|
120
|
+
begin
|
121
|
+
# 1641 = ERROR_SUCCESS_REBOOT_INITIATED
|
122
|
+
# 3010 = ERROR_SUCCESS_REBOOT_REQUIRED
|
123
|
+
on host, Command.new("\"#{batch_path}\"", [], { :cmdexe => true }), :acceptable_exit_codes => [0, 1641, 3010]
|
124
|
+
rescue
|
125
|
+
on host, Command.new("type \"#{log_file}\"", [], { :cmdexe => true })
|
126
|
+
raise
|
127
|
+
end
|
128
|
+
|
129
|
+
if opts[:debug]
|
130
|
+
on host, Command.new("type \"#{log_file}\"", [], { :cmdexe => true })
|
131
|
+
end
|
132
|
+
|
133
|
+
if !host.is_cygwin?
|
134
|
+
# HACK: for some reason, post install we need to refresh the connection to make puppet available for execution
|
135
|
+
host.close
|
136
|
+
end
|
137
|
+
|
138
|
+
# verify service status post install
|
139
|
+
# if puppet service exists, then pe-puppet is not queried
|
140
|
+
# if puppet service does not exist, pe-puppet is queried and that exit code is used
|
141
|
+
# therefore, this command will always exit 0 if either service is installed
|
142
|
+
#
|
143
|
+
# We also take advantage of this output to verify the startup
|
144
|
+
# settings are honored as supplied to the MSI
|
145
|
+
on host, Command.new("sc qc puppet || sc qc pe-puppet", [], { :cmdexe => true }) do |result|
|
146
|
+
output = result.stdout
|
147
|
+
startup_mode = msi_opts['PUPPET_AGENT_STARTUP_MODE'].upcase
|
148
|
+
|
149
|
+
search = case startup_mode
|
150
|
+
when 'AUTOMATIC'
|
151
|
+
{ :code => 2, :name => 'AUTO_START' }
|
152
|
+
when 'MANUAL'
|
153
|
+
{ :code => 3, :name => 'DEMAND_START' }
|
154
|
+
when 'DISABLED'
|
155
|
+
{ :code => 4, :name => 'DISABLED' }
|
156
|
+
end
|
157
|
+
|
158
|
+
if output !~ /^\s+START_TYPE\s+:\s+#{search[:code]}\s+#{search[:name]}/
|
159
|
+
raise "puppet service startup mode did not match supplied MSI option '#{startup_mode}'"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# (PA-514) value for PUPPET_AGENT_STARTUP_MODE should be present in
|
164
|
+
# registry and honored after install/upgrade.
|
165
|
+
reg_key = host.is_x86_64? ? "HKLM\\SOFTWARE\\Wow6432Node\\Puppet Labs\\PuppetInstaller" :
|
166
|
+
"HKLM\\SOFTWARE\\Puppet Labs\\PuppetInstaller"
|
167
|
+
reg_query_command = %Q(reg query "#{reg_key}" /v "RememberedPuppetAgentStartupMode" | findstr #{msi_opts['PUPPET_AGENT_STARTUP_MODE']})
|
168
|
+
on host, Command.new(reg_query_command, [], { :cmdexe => true })
|
169
|
+
|
170
|
+
# emit the misc/versions.txt file which contains component versions for
|
171
|
+
# puppet, facter, hiera, pxp-agent, packaging and vendored Ruby
|
172
|
+
[
|
173
|
+
"\\\"%ProgramFiles%\\Puppet Labs\\puppet\\misc\\versions.txt\\\"",
|
174
|
+
"\\\"%ProgramFiles(x86)%\\Puppet Labs\\puppet\\misc\\versions.txt\\\""
|
175
|
+
].each do |path|
|
176
|
+
on host, Command.new("\"if exist #{path} type #{path}\"", [], { :cmdexe => true })
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Installs a specified msi path on given hosts
|
182
|
+
# @param [Host, Array<Host>, String, Symbol] hosts One or more hosts to act upon,
|
183
|
+
# or a role (String or Symbol) that identifies one or more hosts.
|
184
|
+
# @param [String] msi_path The path of the MSI - can be a local Windows style file path like
|
185
|
+
# c:\temp\foo.msi OR a url like https://download.com/foo.msi or file://c:\temp\foo.msi
|
186
|
+
# @param [Hash{String=>String}] msi_opts MSI installer options
|
187
|
+
# @option opts [Boolean] :debug output the MSI installation log when set to true
|
188
|
+
# otherwise do not output log (false; default behavior)
|
189
|
+
#
|
190
|
+
# @example
|
191
|
+
# generic_install_msi_on(hosts, 'https://releases.hashicorp.com/vagrant/1.8.4/vagrant_1.8.4.msi', {}, {:debug => true})
|
192
|
+
#
|
193
|
+
# @api private
|
194
|
+
def generic_install_msi_on(hosts, msi_path, msi_opts = {}, opts = {})
|
195
|
+
block_on hosts do | host |
|
196
|
+
batch_path, log_file = create_install_msi_batch_on(host, msi_path, msi_opts)
|
197
|
+
|
198
|
+
# begin / rescue here so that we can reuse existing error msg propagation
|
199
|
+
begin
|
200
|
+
# 1641 = ERROR_SUCCESS_REBOOT_INITIATED
|
201
|
+
# 3010 = ERROR_SUCCESS_REBOOT_REQUIRED
|
202
|
+
on host, Command.new("\"#{batch_path}\"", [], { :cmdexe => true }), :acceptable_exit_codes => [0, 1641, 3010]
|
203
|
+
rescue
|
204
|
+
on host, Command.new("type \"#{log_file}\"", [], { :cmdexe => true })
|
205
|
+
raise
|
206
|
+
end
|
207
|
+
|
208
|
+
if opts[:debug]
|
209
|
+
on host, Command.new("type \"#{log_file}\"", [], { :cmdexe => true })
|
210
|
+
end
|
211
|
+
|
212
|
+
if !host.is_cygwin?
|
213
|
+
# HACK: for some reason, post install we need to refresh the connection to make puppet available for execution
|
214
|
+
host.close
|
215
|
+
end
|
216
|
+
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -5,7 +5,7 @@ class ClassMixedWithDSLHelpers
|
|
5
5
|
include Beaker::DSL::Wrappers
|
6
6
|
include Beaker::DSL::Roles
|
7
7
|
include Beaker::DSL::Patterns
|
8
|
-
|
8
|
+
include Beaker::DSL::Helpers::FacterHelpers
|
9
9
|
# include Beaker::DSL::Wrappers
|
10
10
|
# include BeakerTestHelpers
|
11
11
|
|
@@ -7,8 +7,6 @@ class ClassMixedWithDSLHelpers
|
|
7
7
|
include Beaker::DSL::Patterns
|
8
8
|
include Beaker::DSL::Outcomes
|
9
9
|
include Beaker::DSL::Helpers::PuppetHelpers
|
10
|
-
# include Beaker::DSL::Wrappers
|
11
|
-
# include BeakerTestHelpers
|
12
10
|
|
13
11
|
def logger
|
14
12
|
RSpec::Mocks::Double.new('logger').as_null_object
|
@@ -29,6 +27,98 @@ describe ClassMixedWithDSLHelpers do
|
|
29
27
|
let( :db ) { make_host( 'db', :roles => %w( database agent ) ) }
|
30
28
|
let( :hosts ) { [ master, agent, dash, db, custom ] }
|
31
29
|
|
30
|
+
describe '#create_tmpdir_on' do
|
31
|
+
let(:host) { {'user' => 'puppet', 'group' => 'muppets'} }
|
32
|
+
let(:result_success) { double.as_null_object }
|
33
|
+
let(:result_failure) { double.as_null_object }
|
34
|
+
let(:tmpdir) { '/tmp/beaker.XXXXXX/' }
|
35
|
+
|
36
|
+
before :each do
|
37
|
+
allow( host ).to receive( :tmpdir ).and_return( tmpdir )
|
38
|
+
allow( host ).to receive( :result ).and_return( result_success )
|
39
|
+
allow( result_success ).to receive( :success? ).and_return( true )
|
40
|
+
allow( result_success ).to receive( :stdout ).and_return( 'puppet' )
|
41
|
+
allow( result_failure ).to receive( :success? ).and_return( false )
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with the path_prefix argument' do
|
45
|
+
it 'passes path_prefix to host.tmpdir' do
|
46
|
+
expect( host ).to receive( :tmpdir ).with( 'beaker' )
|
47
|
+
subject.create_tmpdir_on( host, 'beaker' )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'with the user argument' do
|
52
|
+
it 'calls chown when a user is specified' do
|
53
|
+
expect( host ).to receive( :user_get ).and_return( result_success )
|
54
|
+
expect( host ).to receive( :chown ).with( host['user'], tmpdir )
|
55
|
+
|
56
|
+
subject.create_tmpdir_on( host, 'beaker', host['user'] )
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'does not call chown when a user is not specified' do
|
60
|
+
expect( host ).to_not receive( :chown )
|
61
|
+
|
62
|
+
subject.create_tmpdir_on( host, 'beaker' )
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'does not call chown and cleans up when the user does not exist on the host' do
|
66
|
+
expect( host ).to receive( :user_get ).and_return( result_failure )
|
67
|
+
expect( host ).to receive( :rm_rf ).with( tmpdir )
|
68
|
+
|
69
|
+
expect{
|
70
|
+
subject.create_tmpdir_on( host, 'beaker', 'invalid.user' )
|
71
|
+
}.to raise_error( RuntimeError, /User invalid.user does not exist on / )
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'with the group argument' do
|
76
|
+
it 'calls chgrp when a group is specified' do
|
77
|
+
expect( host ).to receive( :group_get ).and_return( result_success )
|
78
|
+
expect( host ).to receive( :chgrp ).with( host['group'], tmpdir )
|
79
|
+
|
80
|
+
subject.create_tmpdir_on( host, 'beaker', nil, host['group'] )
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'does not call chgrp when a group is not specified' do
|
84
|
+
expect( subject ).to_not receive( :chgrp )
|
85
|
+
|
86
|
+
subject.create_tmpdir_on( host, 'beaker' )
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'does not call chgrp and cleans up when the group does not exist on the host' do
|
90
|
+
expect( host ).to receive( :group_get ).and_return( result_failure )
|
91
|
+
expect( host ).to receive( :rm_rf ).with( tmpdir )
|
92
|
+
|
93
|
+
expect{
|
94
|
+
subject.create_tmpdir_on( host, 'beaker', nil, 'invalid.group' )
|
95
|
+
}.to raise_error( RuntimeError, /Group invalid.group does not exist on / )
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with user and group arguments' do
|
100
|
+
# don't coalesce the group into chown, i.e. `chown user:group`
|
101
|
+
# this keeps execution paths simple, clean, and discrete
|
102
|
+
it 'calls chown and chgrp separately' do
|
103
|
+
expect( host ).to receive( :user_get ).and_return( result_success )
|
104
|
+
expect( host ).to receive( :group_get ).and_return( result_success )
|
105
|
+
expect( host ).to receive( :chown ).with( host['user'], tmpdir )
|
106
|
+
expect( host ).to receive( :chgrp ).with( host['group'], tmpdir )
|
107
|
+
|
108
|
+
subject.create_tmpdir_on( host, 'beaker', host['user'], host['group'] )
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'does not pass group to chown' do
|
112
|
+
allow( host ).to receive( :user_get ).and_return( result_success )
|
113
|
+
allow( host ).to receive( :chgrp ).with( host['group'], tmpdir )
|
114
|
+
|
115
|
+
expect( host ).to receive( :group_get ).and_return( result_success )
|
116
|
+
expect( host ).to receive( :chown ).with( host['user'], tmpdir )
|
117
|
+
|
118
|
+
subject.create_tmpdir_on( host, 'beaker', host['user'], host['group'] )
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
32
122
|
|
33
123
|
describe '#create_tmpdir_for_user' do
|
34
124
|
let(:host) { {} }
|
@@ -5,9 +5,7 @@ class ClassMixedWithDSLHelpers
|
|
5
5
|
include Beaker::DSL::Wrappers
|
6
6
|
include Beaker::DSL::Roles
|
7
7
|
include Beaker::DSL::Patterns
|
8
|
-
|
9
|
-
# include Beaker::DSL::Wrappers
|
10
|
-
# include BeakerTestHelpers
|
8
|
+
include Beaker::DSL::Helpers::TKHelpers
|
11
9
|
|
12
10
|
def logger
|
13
11
|
RSpec::Mocks::Double.new('logger').as_null_object
|
@@ -0,0 +1,279 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
EZBAKE_CONFIG_EXAMPLE= {
|
4
|
+
:project => 'puppetserver',
|
5
|
+
:real_name => 'puppetserver',
|
6
|
+
:user => 'puppet',
|
7
|
+
:group => 'puppet',
|
8
|
+
:uberjar_name => 'puppetserver-release.jar',
|
9
|
+
:config_files => [],
|
10
|
+
:terminus_info => {},
|
11
|
+
:debian => { :additional_dependencies => ["puppet (= 3.6.1-puppetlabs1)"], },
|
12
|
+
:redhat => { :additional_dependencies => ["puppet = 3.6.1"], },
|
13
|
+
:java_args => '-Xmx192m',
|
14
|
+
}
|
15
|
+
|
16
|
+
class ClassMixedWithEZBakeUtils
|
17
|
+
include Beaker::DSL::EZBakeUtils
|
18
|
+
|
19
|
+
def initialize_ezbake_config
|
20
|
+
Beaker::DSL::EZBakeUtils.config = EZBAKE_CONFIG_EXAMPLE
|
21
|
+
end
|
22
|
+
|
23
|
+
def wipe_out_ezbake_config
|
24
|
+
Beaker::DSL::EZBakeUtils.config = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def logger
|
28
|
+
@logger ||= RSpec::Mocks::Double.new('logger').as_null_object
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module Beaker::DSL::EZBakeUtils::EZBake
|
33
|
+
Config = EZBAKE_CONFIG_EXAMPLE
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ClassMixedWithEZBakeUtils do
|
37
|
+
let( :opts ) { Beaker::Options::Presets.env_vars }
|
38
|
+
let( :host ) { double.as_null_object }
|
39
|
+
let( :local_commands ) { Beaker::DSL::EZBakeUtils::LOCAL_COMMANDS_REQUIRED }
|
40
|
+
|
41
|
+
describe '#install_from_ezbake' do
|
42
|
+
let(:platform) { Beaker::Platform.new('el-7-i386') }
|
43
|
+
let(:host) do
|
44
|
+
FakeHost.create('fakevm', platform.to_s)
|
45
|
+
end
|
46
|
+
|
47
|
+
before do
|
48
|
+
allow(subject).to receive(:ezbake_tools_available?) { true }
|
49
|
+
end
|
50
|
+
|
51
|
+
it "when ran with an el-7 machine runs correct installsh command" do
|
52
|
+
expect(subject).to receive(:install_ezbake_tarball_on_host).
|
53
|
+
ordered
|
54
|
+
expect(subject).
|
55
|
+
to receive(:ezbake_installsh).with(host, "service")
|
56
|
+
subject.install_from_ezbake host
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#install_termini_from_ezbake' do
|
61
|
+
let(:platform) { Beaker::Platform.new('el-7-i386') }
|
62
|
+
let(:host) do
|
63
|
+
FakeHost.create('fakevm', platform.to_s)
|
64
|
+
end
|
65
|
+
|
66
|
+
before do
|
67
|
+
allow(subject).to receive(:ezbake_tools_available?) { true }
|
68
|
+
end
|
69
|
+
|
70
|
+
it "when ran with an el-7 machine runs correct installsh command" do
|
71
|
+
expect(subject).to receive(:ezbake_validate_support).with(host).ordered
|
72
|
+
expect(subject).to receive(:install_ezbake_tarball_on_host).
|
73
|
+
with(host).ordered
|
74
|
+
expect(subject).
|
75
|
+
to receive(:ezbake_installsh).with(host, "termini")
|
76
|
+
subject.install_termini_from_ezbake host
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#ezbake_validate_support' do
|
81
|
+
context 'when OS supported' do
|
82
|
+
let(:platform) { Beaker::Platform.new('el-7-i386') }
|
83
|
+
let(:host) do
|
84
|
+
FakeHost.create('fakevm', platform.to_s)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should do nothing' do
|
88
|
+
subject.ezbake_validate_support host
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when OS not supported' do
|
93
|
+
let(:platform) { Beaker::Platform.new('aix-12-ppc') }
|
94
|
+
let(:host) do
|
95
|
+
FakeHost.create('fakevm', platform.to_s)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should throw exception' do
|
99
|
+
expect {
|
100
|
+
subject.ezbake_validate_support host
|
101
|
+
}.to raise_error(RuntimeError,
|
102
|
+
"No support for aix within ezbake_utils ...")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def install_ezbake_tarball_on_host_common_expects
|
108
|
+
result = object_double(Beaker::Result.new(host, "foo"), :exit_code => 1)
|
109
|
+
expect(subject).to receive(:on).
|
110
|
+
with(kind_of(Beaker::Host), /test -d/,
|
111
|
+
anything()).ordered { result }
|
112
|
+
expect(Dir).to receive(:chdir).and_yield()
|
113
|
+
expect(subject).to receive(:ezbake_local_cmd).with(/rake package:tar/).ordered
|
114
|
+
expect(subject).to receive(:scp_to).
|
115
|
+
with(kind_of(Beaker::Host), anything(), anything()).ordered
|
116
|
+
expect(subject).to receive(:on).
|
117
|
+
with(kind_of(Beaker::Host), /tar -xzf/).ordered
|
118
|
+
expect(subject).to receive(:on).
|
119
|
+
with(kind_of(Beaker::Host), /test -d/).ordered
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '#install_ezbake_tarball_on_host' do
|
123
|
+
let(:platform) { Beaker::Platform.new('el-7-i386') }
|
124
|
+
let(:host) do
|
125
|
+
FakeHost.create('fakevm', platform.to_s)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'when invoked with configuration should run expected tasks' do
|
129
|
+
subject.initialize_ezbake_config
|
130
|
+
install_ezbake_tarball_on_host_common_expects
|
131
|
+
subject.install_ezbake_tarball_on_host host
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'when invoked with nil configuration runs ezbake_stage' do
|
135
|
+
subject.wipe_out_ezbake_config
|
136
|
+
expect(subject).to receive(:ezbake_stage) {
|
137
|
+
Beaker::DSL::EZBakeUtils.config = EZBAKE_CONFIG_EXAMPLE
|
138
|
+
}.ordered
|
139
|
+
install_ezbake_tarball_on_host_common_expects
|
140
|
+
subject.install_ezbake_tarball_on_host host
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe '#ezbake_tools_available?' do
|
145
|
+
before do
|
146
|
+
allow(subject).to receive(:check_for_package) { true }
|
147
|
+
allow(subject).to receive(:system) { true }
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "checks for local successful commands" do
|
151
|
+
|
152
|
+
it "and succeeds if all commands return successfully" do
|
153
|
+
local_commands.each do |software_name, command, additional_error_messages|
|
154
|
+
expect(subject).to receive(:system).with(/#{command}/)
|
155
|
+
end
|
156
|
+
subject.ezbake_tools_available?
|
157
|
+
end
|
158
|
+
|
159
|
+
it "and raises an exception if a command returns failure" do
|
160
|
+
allow(subject).to receive(:system) { false }
|
161
|
+
local_commands.each do |software_name, command, additional_error_messages|
|
162
|
+
expect(subject).to receive(:system).with(/#{command}/)
|
163
|
+
break # just need first element
|
164
|
+
end
|
165
|
+
expect{
|
166
|
+
subject.ezbake_tools_available?
|
167
|
+
}.to raise_error(RuntimeError, /Must have .* installed on development system./)
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
describe '#ezbake_config' do
|
175
|
+
it "returns a map with ezbake configuration parameters" do
|
176
|
+
subject.initialize_ezbake_config
|
177
|
+
config = subject.ezbake_config
|
178
|
+
expect(config).to include(EZBAKE_CONFIG_EXAMPLE)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe '#ezbake_stage' do
|
183
|
+
before do
|
184
|
+
allow(subject).to receive(:ezbake_tools_available?) { true }
|
185
|
+
subject.wipe_out_ezbake_config
|
186
|
+
end
|
187
|
+
|
188
|
+
it "initializes EZBakeUtils.config" do
|
189
|
+
allow(Dir).to receive(:chdir).and_yield()
|
190
|
+
|
191
|
+
expect(subject).to receive(:ezbake_local_cmd).
|
192
|
+
with(/^lein.*install/, :throw_on_failure =>
|
193
|
+
true).ordered
|
194
|
+
expect(subject).to receive(:ezbake_local_cmd).
|
195
|
+
with(/^lein.*with-profile ezbake ezbake stage/, :throw_on_failure =>
|
196
|
+
true).ordered
|
197
|
+
expect(subject).to receive(:ezbake_local_cmd).with("rake package:bootstrap").ordered
|
198
|
+
expect(subject).to receive(:load) { }.ordered
|
199
|
+
expect(subject).to receive(:`).ordered
|
200
|
+
|
201
|
+
config = subject.ezbake_config
|
202
|
+
expect(config).to eq(nil)
|
203
|
+
|
204
|
+
subject.ezbake_stage
|
205
|
+
|
206
|
+
config = subject.ezbake_config
|
207
|
+
expect(config).to include(EZBAKE_CONFIG_EXAMPLE)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe '#ezbake_local_cmd' do
|
212
|
+
it 'should execute system on the command specified' do
|
213
|
+
expect(subject).to receive(:system).with("my command") { true }
|
214
|
+
subject.ezbake_local_cmd("my command")
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'with :throw_on_failure should throw exeception when failed' do
|
218
|
+
expect(subject).to receive(:system).with("my failure") { false }
|
219
|
+
expect {
|
220
|
+
subject.ezbake_local_cmd("my failure", :throw_on_failure => true)
|
221
|
+
}.to raise_error(RuntimeError, "Command failure my failure")
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'without :throw_on_failure should just fail and return false' do
|
225
|
+
expect(subject).to receive(:system).with("my failure") { false }
|
226
|
+
expect(subject.ezbake_local_cmd("my failure")).to eq(false)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe '#ezbake_install_name' do
|
231
|
+
it 'should return the installation name from example configuration' do
|
232
|
+
expect(subject).to receive(:ezbake_config) {{
|
233
|
+
:package_version => '1.1.1',
|
234
|
+
:project => 'myproject',
|
235
|
+
}}
|
236
|
+
expect(subject.ezbake_install_name).to eq "myproject-1.1.1"
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe '#ezbake_install_dir' do
|
241
|
+
it 'should return the full path from ezbake_install_name' do
|
242
|
+
expect(subject).to receive(:ezbake_install_name) {
|
243
|
+
"mynewproject-2.3.4"
|
244
|
+
}
|
245
|
+
expect(subject.ezbake_install_dir).to eq "/root/mynewproject-2.3.4"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe '#ezbake_installsh' do
|
250
|
+
it 'run on command correctly when invoked' do
|
251
|
+
expect(subject).to receive(:on).with(host,
|
252
|
+
/install.sh my_task/)
|
253
|
+
subject.ezbake_installsh host, "my_task"
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe '#conditionally_clone' do
|
258
|
+
it 'when repo exists, just do fetch and checkout' do
|
259
|
+
expect(subject).to receive(:ezbake_local_cmd).
|
260
|
+
with(/git status/) { true }
|
261
|
+
expect(subject).to receive(:ezbake_local_cmd).
|
262
|
+
with(/git fetch origin/)
|
263
|
+
expect(subject).to receive(:ezbake_local_cmd).
|
264
|
+
with(/git checkout/)
|
265
|
+
subject.conditionally_clone("my_url", "my_local_path")
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'when repo does not exist, do clone and checkout' do
|
269
|
+
expect(subject).to receive(:ezbake_local_cmd).
|
270
|
+
with(/git status/) { false }
|
271
|
+
expect(subject).to receive(:ezbake_local_cmd).
|
272
|
+
with(/git clone/)
|
273
|
+
expect(subject).to receive(:ezbake_local_cmd).
|
274
|
+
with(/git checkout/)
|
275
|
+
subject.conditionally_clone("my_url", "my_local_path")
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|