Skip to content

Commit 9d48894

Browse files
authored
Merge pull request #200 from wilson208/PE-17491
[PE-17491] Do not fail on install when a restart exit code is returned
2 parents e8721c6 + 2805aa6 commit 9d48894

File tree

6 files changed

+116
-26
lines changed

6 files changed

+116
-26
lines changed

lib/puppet/provider/sqlserver.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,19 @@ class Puppet::Provider::Sqlserver < Puppet::Provider
1717
'powershell.exe'
1818
end
1919

20-
def try_execute(command, msg = nil, obfuscate_strings = nil)
21-
begin
22-
execute(command.compact)
23-
rescue Puppet::ExecutionFailure => error
20+
def try_execute(command, msg = nil, obfuscate_strings = nil, acceptable_exit_codes = [0])
21+
res = execute(command.compact, failonfail: false)
22+
23+
unless acceptable_exit_codes.include?(res.exitstatus)
2424
msg = "Failure occured when trying to install SQL Server #{@resource[:name]}" if msg.nil?
25-
msg += " \n #{error}"
25+
msg += " \n Execution of '#{command}' returned #{res.exitstatus}: #{res.strip}"
2626

2727
obfuscate_strings.each {|str| msg.gsub!(str, '**HIDDEN VALUE**') } unless obfuscate_strings.nil?
2828

2929
raise Puppet::Error, msg
3030
end
31+
32+
res
3133
end
3234

3335
private

lib/puppet/provider/sqlserver_features/mssql.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ def modify_features(action, features)
6464
begin
6565
config_file = create_temp_for_install_switch unless action == 'uninstall'
6666
cmd_args << "/ConfigurationFile=\"#{config_file.path}\"" unless config_file.nil?
67-
try_execute(cmd_args, "Unable to #{action} features (#{features.join(', ')})")
67+
res = try_execute(cmd_args, "Unable to #{action} features (#{features.join(', ')})", nil, [0, 1641, 3010])
68+
69+
warn("#{action} of features (#{features.join(', ')} returned exit code 3010 - reboot required") if res.exitstatus == 3010
70+
warn("#{action} of features (#{features.join(', ')} returned exit code 1641 - reboot initiated") if res.exitstatus == 1641
6871
ensure
6972
if config_file
7073
config_file.close

lib/puppet/provider/sqlserver_instance/mssql.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ def modify_features(features, action)
4848
begin
4949
config_file = create_temp_for_install_switch unless action == 'uninstall'
5050
cmd_args << "/ConfigurationFile=\"#{config_file.path}\"" unless config_file.nil?
51-
try_execute(cmd_args, "Error trying to #{action} features (#{features.join(', ')}", obfuscated_strings)
51+
res = try_execute(cmd_args, "Error trying to #{action} features (#{features.join(', ')}", obfuscated_strings, [0, 1641, 3010])
52+
53+
warn("#{action} of features (#{features.join(', ')}) returned exit code 3010 - reboot required") if res.exitstatus == 3010
54+
warn("#{action} of features (#{features.join(', ')}) returned exit code 1641 - reboot initiated") if res.exitstatus == 1641
5255
ensure
5356
if config_file
5457
config_file.close
@@ -161,7 +164,11 @@ def format_cmd_args_array(switch, arr, cmd_args, use_discrete = false)
161164

162165
def destroy
163166
cmd_args = basic_cmd_args(current_installed_features, 'uninstall')
164-
try_execute(cmd_args, "Unable to uninstall instance #{@resource[:name]}")
167+
res = try_execute(cmd_args, "Unable to uninstall instance #{@resource[:name]}", nil, [0, 1641, 3010])
168+
169+
warn("Uninstall of instance #{@resource[:name]} returned exit code 3010 - reboot required") if res.exitstatus == 3010
170+
warn("Uninstall of instance #{@resource[:name]} returned exit code 1641 - reboot initiated") if res.exitstatus == 1641
171+
165172
@property_hash.clear
166173
exists? ? (return false) : (return true)
167174
end

spec/unit/puppet/provider/sqlserver__instance_spec.rb

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@
1010
subject { provider_class }
1111
let(:additional_install_switches) { [] }
1212

13-
def stub_uninstall(args, installed_features)
13+
def stub_uninstall(args, installed_features, exit_code = 0)
1414
cmd_args = ["#{args[:source]}/setup.exe",
1515
"/ACTION=uninstall",
1616
'/Q',
1717
'/IACCEPTSQLSERVERLICENSETERMS',
1818
"/INSTANCENAME=#{args[:name]}",
1919
"/FEATURES=#{installed_features.join(',')}",]
20-
Puppet::Util::Execution.stubs(:execute).with(cmd_args.compact).returns(0)
20+
21+
result = Puppet::Util::Execution::ProcessOutput.new('', exit_code)
22+
Puppet::Util::Execution.stubs(:execute).with(cmd_args.compact, failonfail: false).returns(result)
2123
end
2224

2325
shared_examples 'run' do |args, munged_values = {}|
@@ -46,7 +48,7 @@ def stub_uninstall(args, installed_features)
4648
@provider.create
4749
}
4850
end
49-
shared_examples 'create' do
51+
shared_examples 'create' do |exit_code, warning_matcher|
5052
it {
5153
execute_args = args.merge(munged_values)
5254
@resource = Puppet::Type::Sqlserver_instance.new(args)
@@ -77,20 +79,27 @@ def stub_uninstall(args, installed_features)
7779
additional_install_switches.each do |switch|
7880
cmd_args << switch
7981
end
80-
Puppet::Util::Execution.stubs(:execute).with(cmd_args.compact).returns(0)
82+
83+
# If warning_matcher supplied ensure warnings raised match, otherwise no warnings raised
84+
@provider.stubs(:warn).with(regexp_matches(warning_matcher)).returns(nil).times(1) if warning_matcher
85+
@provider.stubs(:warn).with(anything).times(0) unless warning_matcher
86+
87+
result = Puppet::Util::Execution::ProcessOutput.new('', exit_code || 0)
88+
Puppet::Util::Execution.stubs(:execute).with(cmd_args.compact, failonfail: false).returns(result)
8189
@provider.create
8290
}
8391
end
8492

8593

86-
shared_examples 'destroy' do
94+
shared_examples 'destroy' do |exit_code, warning_matcher|
8795
it {
8896
@resource = Puppet::Type::Sqlserver_instance.new(args)
8997
@provider = provider_class.new(@resource)
9098

9199
stub_source_which_call args[:source]
92100
@provider.expects(:current_installed_features).returns(installed_features)
93-
stub_uninstall args, installed_features
101+
stub_uninstall args, installed_features, exit_code || 0
102+
@provider.stubs(:warn).with(regexp_matches(warning_matcher)).returns(nil).times(1) if warning_matcher
94103
@provider.destroy
95104
}
96105
end
@@ -118,6 +127,30 @@ def stub_uninstall(args, installed_features)
118127
end
119128
end
120129

130+
describe 'it should raise warning on install when 1641 exit code returned' do
131+
it_behaves_like 'create', 1641, /reboot initiated/i do
132+
args = get_basic_args
133+
let(:args) { args }
134+
munged = {:features => Array.new(args[:features])}
135+
munged[:features].delete('SQL')
136+
munged[:features] += %w(DQ FullText Replication SQLEngine)
137+
munged[:features].sort!
138+
let(:munged_values) { munged }
139+
end
140+
end
141+
142+
describe 'it should raise warning on install when 3010 exit code returned' do
143+
it_behaves_like 'create', 3010, /reboot required/i do
144+
args = get_basic_args
145+
let(:args) { args }
146+
munged = {:features => Array.new(args[:features])}
147+
munged[:features].delete('SQL')
148+
munged[:features] += %w(DQ FullText Replication SQLEngine)
149+
munged[:features].sort!
150+
let(:munged_values) { munged }
151+
end
152+
end
153+
121154
describe 'empty array should' do
122155
it_behaves_like 'destroy on create' do
123156
let(:installed_features) { %w(SQLEngine Replication) }
@@ -140,6 +173,29 @@ def stub_uninstall(args, installed_features)
140173
end
141174

142175
end
176+
177+
describe 'it should raise warning on uninstall when 1641 exit code returned' do
178+
it_behaves_like 'destroy', 1641, /reboot initiated/i do
179+
let(:args) { {
180+
:name => 'MYSQLSERVER',
181+
:source => 'C:\myinstallexecs',
182+
:features => []
183+
} }
184+
let(:installed_features) { %w(SQLEngine Replication) }
185+
end
186+
end
187+
188+
describe 'it should raise warning on uninstall when 3010 exit code returned' do
189+
it_behaves_like 'destroy', 3010, /reboot required/i do
190+
let(:args) { {
191+
:name => 'MYSQLSERVER',
192+
:source => 'C:\myinstallexecs',
193+
:features => []
194+
} }
195+
let(:installed_features) { %w(SQLEngine Replication) }
196+
end
197+
end
198+
143199
describe 'installed features even if provided features' do
144200
it_behaves_like 'destroy' do
145201
let(:args) { {

spec/unit/puppet/provider/sqlserver_features_spec.rb

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
let(:additional_params) { {} }
1616
let(:munged_args) { {} }
1717
let(:additional_switches) { [] }
18-
shared_examples 'create' do
18+
shared_examples 'create' do |exit_code, warning_matcher|
1919
it {
2020
params.merge!(additional_params)
2121
@resource = Puppet::Type::Sqlserver_features.new(params)
@@ -24,7 +24,8 @@
2424
stub_powershell_call(subject)
2525

2626
executed_args = params.merge(munged_args)
27-
stub_add_features(executed_args, executed_args[:features], additional_switches)
27+
stub_add_features(executed_args, executed_args[:features], additional_switches, exit_code || 0)
28+
@provider.stubs(:warn).with(regexp_matches(warning_matcher)).returns(nil).times(1) if warning_matcher
2829
@provider.create
2930
}
3031
end
@@ -65,20 +66,23 @@
6566
it_should_behave_like 'create'
6667
end
6768

68-
shared_examples 'features=' do |args|
69+
shared_examples 'features=' do |args, exit_code, warning_matcher|
6970
it {
7071
@resource = Puppet::Type::Sqlserver_features.new(args)
7172
@provider = provider_class.new(@resource)
7273

7374
stub_powershell_call(subject)
7475
stub_source_which_call args
7576
if !feature_remove.empty?
76-
stub_remove_features(args, feature_remove)
77+
stub_remove_features(args, feature_remove, exit_code || 0)
7778
end
7879
if !feature_add.empty?
79-
stub_add_features(args, feature_add)
80+
stub_add_features(args, feature_add, [], exit_code || 0)
8081
end
8182

83+
# If warning_matcher supplied ensure warnings raised match, otherwise no warnings raised
84+
@provider.stubs(:warn).with(regexp_matches(warning_matcher)).returns(nil).times(1) if warning_matcher
85+
@provider.stubs(:warn).with(anything).times(0) unless warning_matcher
8286
@provider.create
8387
}
8488
end
@@ -106,6 +110,20 @@
106110
it_should_behave_like 'features=', @feature_params
107111
end
108112

113+
context 'it should raise warning on feature install when 1641 exit code returned' do
114+
include_context 'features'
115+
@feature_params[:features] = %w(SSMS)
116+
let(:feature_add) { %w(SSMS) }
117+
it_should_behave_like 'features=', @feature_params, 1641, /reboot initiated/i
118+
end
119+
120+
context 'it should raise warning on feature install when 3010 exit code returned' do
121+
include_context 'features'
122+
@feature_params[:features] = %w(SSMS)
123+
let(:feature_add) { %w(SSMS) }
124+
it_should_behave_like 'features=', @feature_params, 3010, /reboot required/i
125+
end
126+
109127
context 'it should install the expanded tools set' do
110128
include_context 'features'
111129
@feature_params[:features] = %w(Tools)
@@ -131,13 +149,14 @@
131149
@provider = provider_class.new(@resource)
132150
@provider.stubs(:current_installed_features).returns(%w(SSMS ADV_SSMS Conn))
133151
Puppet::Util.stubs(:which).with("#{feature_params[:source]}/setup.exe").returns("#{feature_params[:source]}/setup.exe")
152+
result = Puppet::Util::Execution::ProcessOutput.new('', 0)
134153
Puppet::Util::Execution.expects(:execute).with(
135154
["#{feature_params[:source]}/setup.exe",
136155
"/ACTION=uninstall",
137156
'/Q',
138157
'/IACCEPTSQLSERVERLICENSETERMS',
139158
"/FEATURES=#{%w(SSMS ADV_SSMS Conn).join(',')}",
140-
]).returns(0)
159+
], failonfail: false).returns(result)
141160
@provider.create
142161
}
143162
end

spec/unit/puppet/sqlserver_spec_helper.rb

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ def stub_powershell_call(subject)
77
Puppet::Provider::Sqlserver.stubs(:run_install_dot_net).returns()
88
end
99

10-
def stub_add_features(args, features, additional_switches = [])
11-
stub_modify_features('install', args, features, additional_switches)
10+
def stub_add_features(args, features, additional_switches = [], exit_code = 0)
11+
stub_modify_features('install', args, features, additional_switches, exit_code)
1212
end
1313

14-
def stub_remove_features(args, features)
15-
stub_modify_features('uninstall', args, features)
14+
def stub_remove_features(args, features, exit_code = 0)
15+
stub_modify_features('uninstall', args, features, [], exit_code)
1616
end
1717

18-
def stub_modify_features(action, args, features, additional_switches = [])
18+
def stub_modify_features(action, args, features, additional_switches = [], exit_code = 0)
1919
cmds = ["#{args[:source]}/setup.exe",
2020
"/ACTION=#{action}",
2121
'/Q',
@@ -31,5 +31,8 @@ def stub_modify_features(action, args, features, additional_switches = [])
3131
additional_switches.each do |switch|
3232
cmds << switch
3333
end
34-
Puppet::Util::Execution.stubs(:execute).with(cmds).returns(0)
34+
35+
result = Puppet::Util::Execution::ProcessOutput.new('', exit_code)
36+
37+
Puppet::Util::Execution.stubs(:execute).with(cmds, failonfail: false).returns(result)
3538
end

0 commit comments

Comments
 (0)