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.
@@ -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
@@ -1,3 +1,3 @@
1
1
  module BeakerPuppet
2
- VERSION = '0.17.1'
2
+ VERSION = '1.0.0'
3
3
  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
- # include Beaker::DSL::Helpers::FacterHelpers
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
- # include Beaker::DSL::Helpers::TKHelpers
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