diff --git a/Gemfile b/Gemfile index 53b9c1f..e66eda7 100644 --- a/Gemfile +++ b/Gemfile @@ -4,3 +4,5 @@ source 'https://rubygems.org' # Specify your gem's dependencies in sensu-plugin-minio.gemspec gemspec + +gem 'parallel', '< 1.20.0' diff --git a/Gemfile.lock b/Gemfile.lock index d266c61..9cc771d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,7 +17,7 @@ GEM jaro_winkler (1.5.4) json (2.6.2) mixlib-cli (1.7.0) - parallel (1.22.1) + parallel (1.19.2) parser (3.1.2.0) ast (~> 2.4.1) public_suffix (4.0.7) @@ -60,6 +60,7 @@ PLATFORMS DEPENDENCIES bundler (~> 2.1) + parallel (< 1.20.0) rake (~> 13.0) rspec (~> 3.10) rubocop (~> 0.54, <= 0.81) diff --git a/bin/check-minio-update.rb b/bin/check-minio-update.rb index 9925773..4af034f 100755 --- a/bin/check-minio-update.rb +++ b/bin/check-minio-update.rb @@ -21,6 +21,8 @@ class CheckMinioUpdate < Sensu::Plugin::Check::CLI include Sensu::Plugin::Utils + RELEASE_PATTERN = /(?RELEASE.\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z)/.freeze # rubocop:disable Layout/LineLength + option :checkurl, description: 'Base URL to check for updates', short: '-u URL', @@ -39,49 +41,55 @@ class CheckMinioUpdate < Sensu::Plugin::Check::CLI default: 30 def run - checkurl = config[:checkurl] - platform = config[:platform] - timeout = config[:timeout].to_i - - begin - Timeout.timeout(timeout) do - latest_version = get_latest_version(checkurl, platform) - - if local_version == latest_version - ok 'No new minio version available' - else - critical "New minio version available #{latest_version}" - end + Timeout.timeout(config[:timeout].to_i) do + if local_version == latest_version + ok 'No new minio version available' + else + critical "New minio version available #{latest_version}" end - rescue IOError => e - unknown e.message.to_s - rescue Timeout::Error - unknown 'Connection timed out' end + rescue IOError => e + unknown e.message.to_s + rescue Timeout::Error + unknown 'Connection timed out' end private - def get_latest_version(checkurl, platform) - uri = URI.parse("#{checkurl}/#{platform}/minio.shasum") - response = Net::HTTP.get_response(uri) + def latest_version + @latest_version ||= begin + uri = URI.parse("#{config[:checkurl]}/#{config[:platform]}/minio.shasum") + response = Net::HTTP.get_response(uri) - unless response.is_a?(Net::HTTPSuccess) - raise IOError, "Unable to gather latest minio version: #{response.body}" - end + unless response.is_a?(Net::HTTPSuccess) + raise IOError, "Unable to gather latest minio version: #{response.body}" + end - response.body.split.last.split('.', 2).last + extract_release(response.body) + end end def local_version - stdout, stderr, status = Open3.capture3( - { 'PATH' => ENV['PATH'] }, 'minio --version', unsetenv_others: true - ) + @local_version ||= begin + stdout, stderr, status = Open3.capture3( + { 'PATH' => ENV['PATH'] }, 'minio --version', unsetenv_others: true + ) + + unless status.success? + raise IOError, "Unable to gather local minio version: #{stderr}" + end + + extract_release(stdout) + end + end + + def extract_release(release_source_str) + match_data = RELEASE_PATTERN.match(release_source_str) - unless status.success? - raise IOError, "Unable to gather local minio version: #{stderr}" + if match_data.nil? + raise IOError, "Unable to extract release: #{release_source_str}" end - stdout.lines.first.split.last + match_data[:release] end end diff --git a/spec/check_minio_update_spec.rb b/spec/check_minio_update_spec.rb index 0676912..818d3ec 100644 --- a/spec/check_minio_update_spec.rb +++ b/spec/check_minio_update_spec.rb @@ -23,9 +23,7 @@ let(:response) do { - body: - '285ec90006a6961ebcb7dd9685acc0ebcd08f561 '\ - 'minio.RELEASE.2021-07-08T19-43-25Z', + body: '3832278ee2bb74d41b617788b4244e410b29e4a8 minio.RELEASE.2022-07-17T15-43-14Z', # rubocop:disable Layout/LineLength status: 200 } end @@ -40,16 +38,14 @@ end let(:stdout) do - "minio version RELEASE.2021-07-08T19-43-25Z\n"\ - "commit: dd53b287f2eeed9cd3872eeae7d64696bfd7829d\n"\ - 'go version: go1.18.3' + 'minio version RELEASE.2022-07-17T15-43-14Z (commit-id=1b339ea062b423f1c6fbeb02116d020d18418917)' # rubocop:disable Layout/LineLength end let(:stderr) { nil } let(:success) { true } context 'with matching local and remote version' do - it 'should be ok if versions are equal' do + it 'should be ok' do expect { check.run }.to raise_error do |error| expect(error).to be_a SystemExit expect(error.status).to eq 0 @@ -58,6 +54,7 @@ expect(check).to have_received(:output).with( 'No new minio version available' ) + expect(checksum_request).to have_been_requested end end @@ -67,7 +64,7 @@ { body: '285ec90006a6961ebcb7dd9685acc0ebcd08f561 '\ - 'minio.RELEASE.2022-07-08T19-43-25Z', + 'minio.RELEASE.3022-07-17T15-43-14Z', status: 200 } end @@ -79,43 +76,89 @@ end expect(check).to have_received(:output).with( - 'New minio version available RELEASE.2022-07-08T19-43-25Z' + 'New minio version available RELEASE.3022-07-17T15-43-14Z' ) + expect(checksum_request).to have_been_requested end end context 'with unknown local version' do - let(:stdout) { nil } - let(:stderr) { 'Minio not found' } - let(:success) { false } - - it 'should be unknown' do - expect { check.run }.to raise_error do |error| - expect(error).to be_a SystemExit - expect(error.status).to eq 3 + context 'when minio executable not found' do + let(:stdout) { nil } + let(:stderr) { 'minio not found' } + let(:success) { false } + + it 'should be unknown' do + expect { check.run }.to raise_error do |error| + expect(error).to be_a SystemExit + expect(error.status).to eq 3 + end + + expect(check).to have_received(:output).with( + 'Unable to gather local minio version: minio not found' + ) + + expect(checksum_request).not_to have_been_requested end + end - expect(check).to have_received(:output).with( - 'Unable to gather local minio version: Minio not found' - ) - expect(checksum_request).to have_been_requested + context 'when release could not be extracted' do + let(:stdout) { 'INVALID' } + + it 'should be unknown' do + expect { check.run }.to raise_error do |error| + expect(error).to be_a SystemExit + expect(error.status).to eq 3 + end + + expect(check).to have_received(:output).with( + 'Unable to extract release: INVALID' + ) + + expect(checksum_request).not_to have_been_requested + end end end - context 'with release url not found' do - let(:response) { { body: '404 Not Found', status: 404 } } + context 'with unknown remote version' do + context 'with release url not found' do + let(:response) { { body: '404 Not Found', status: 404 } } - it 'should be unknown' do - expect { check.run }.to raise_error do |error| - expect(error).to be_a SystemExit - expect(error.status).to eq 3 + it 'should be unknown' do + expect { check.run }.to raise_error do |error| + expect(error).to be_a SystemExit + expect(error.status).to eq 3 + end + + expect(check).to have_received(:output).with( + 'Unable to gather latest minio version: 404 Not Found' + ) + + expect(checksum_request).to have_been_requested end + end - expect(check).to have_received(:output).with( - 'Unable to gather latest minio version: 404 Not Found' - ) - expect(checksum_request).to have_been_requested + context 'when release could not be extracted' do + let(:response) do + { + body: '3832278ee2bb74d41b617788b4244e410b29e4a8 INVALID', + status: 200 + } + end + + it 'should be unknown' do + expect { check.run }.to raise_error do |error| + expect(error).to be_a SystemExit + expect(error.status).to eq 3 + end + + expect(check).to have_received(:output).with( + 'Unable to extract release: 3832278ee2bb74d41b617788b4244e410b29e4a8 INVALID' # rubocop:disable Layout/LineLength + ) + + expect(checksum_request).to have_been_requested + end end end end