beaker-puppet 0.17.1 → 1.0.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.
@@ -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