Skip to content

Commit

Permalink
Catch Net::ReadTimeout exceptions on SCC wizard
Browse files Browse the repository at this point in the history
This commit adds proper timeout exception treatment on the method
`RMT::WizardSCCPage#scc_credentials_valid?`:

* Before: an "Internal error" message would be shown if a request timed
  out when contacting SCC to validate the credentials.
* Now: a popup dialog will be shown, giving the user the choice to retry
  the request or cancel the operation.

Additionally, the request has been enriched with a proper "user agent"
to allow better debugging with SCC.
  • Loading branch information
lcaparroz committed Feb 8, 2024
1 parent e4cf029 commit cc0246d
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 16 deletions.
71 changes: 59 additions & 12 deletions spec/rmt/wizard_scc_page_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,26 +127,73 @@
expect(Yast::UI).to receive(:CloseDialog)

expect_any_instance_of(Net::HTTP::Get).to receive(:basic_auth).with(config['scc']['username'], config['scc']['password'])

expect(Net::HTTP).to receive(:start).and_return(response_double)
expect(response_double).to receive(:code).and_return(response_code)
end

let(:response_double) { instance_double(Net::HTTPResponse) }
context 'when the request completes without errors' do
before do
expect(Net::HTTP).to receive(:start).and_return(response_double)
expect(response_double).to receive(:code).and_return(response_code)
end

let(:response_double) { instance_double(Net::HTTPResponse) }

context 'when HTTP response code is 200' do
let(:response_code) { '200' }
context 'when HTTP response code is 200' do
let(:response_code) { '200' }

it 'returns true' do
expect(scc_page.scc_credentials_valid?).to be(true)
it 'returns true' do
expect(scc_page.scc_credentials_valid?).to be(true)
end
end

context 'when HTTP response code is not 200' do
let(:response_code) { '401' }

it 'returns false' do
expect(scc_page.scc_credentials_valid?).to be(false)
end
end
end

context 'when HTTP response code is not 200' do
let(:response_code) { '401' }
context 'when SCC times out and the user chooses not to try again' do
before do
expect(Yast::Popup).to receive(:ErrorAnyQuestion).and_return(false)
expect(Net::HTTP).to receive(:start).and_raise(Net::ReadTimeout)
end

context 'and the user chooses to not try again' do
it 'returns false' do
expect(scc_page.scc_credentials_valid?).to be(false)
end
end
end

context 'when SCC times out and the user chooses to try again' do
before do
expect(Yast::Popup).to receive(:ErrorAnyQuestion).and_return(true)
expect(Net::HTTP).to receive(:start).and_raise(Net::ReadTimeout)
expect(Net::HTTP).to receive(:start).and_return(response_double)
end

let(:response_double) { instance_double(Net::HTTPResponse) }

context 'when SCC responds quickly and the HTTP response code is 200' do
before do
expect(response_double).to receive(:code).and_return(200)
end

it 'returns true' do
expect(scc_page.scc_credentials_valid?).to be(true)
end
end

context 'when SCC responds quickly and the HTTP response code is not 200' do
before do
expect(response_double).to receive(:code).and_return(401)
end

it 'returns false' do
expect(scc_page.scc_credentials_valid?).to be(false)
it 'returns false' do
expect(scc_page.scc_credentials_valid?).to be(false)
end
end
end
end
Expand Down
23 changes: 19 additions & 4 deletions src/lib/rmt/wizard_scc_page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ module RMT; end
class RMT::WizardSCCPage < Yast::Client
include ::UI::EventDispatcher

YAST_RMT_USER_AGENT = 'yast2-rmt'.freeze

def initialize(config)
textdomain 'rmt'
@config = config
Expand Down Expand Up @@ -126,14 +128,27 @@ def scc_credentials_valid?
)
)

uri = URI('https://scc.suse.com/connect/organizations/systems')
uri = URI('https://scc.suse.com/connect/organizations/orders')
req = Net::HTTP::Get.new(uri)
req.basic_auth(@config['scc']['username'], @config['scc']['password'])

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
req['User-Agent'] = YAST_RMT_USER_AGENT

valid_credentials = nil
while valid_credentials.nil?
begin
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
valid_credentials = (res.code.to_i == 200)
rescue Net::ReadTimeout
break valid_credentials = false unless Popup.ErrorAnyQuestion(
_('Request Timeout'),
_("The request to SCC timed out.\n\nWould you like to try again?"),
_('Retry'), _('Cancel'), :focus_yes
)
end
end

UI.CloseDialog

res.code.to_i == 200
valid_credentials
end
end

0 comments on commit cc0246d

Please sign in to comment.