Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync with upstream repo. #1

Merged
merged 6 commits into from
Sep 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [2.6.0] - 2018-08-28
### Fixed
- Fix `paginated_get` for backward compatibility with Sensu API < 1.4 (@cwjohnston).

## [2.6.0] - 2018-08-28
### Added
- Added utils method `paginated_get` for iteratively retrieving API responses (@cwjohnston).

## [2.5.0] - 2018-04-03
### Added
- Added Handler Sensu API HTTPS support through API configuration (e.g. `{"api": {"ssl": {}}` (@portertech).
Expand Down Expand Up @@ -125,7 +133,9 @@ The changes in earlier releases are not fully documented but comparison links ar
* [v0.1.1]
* [v0.1.0]

[Unreleased]: https://github.com/sensu-plugins/sensu-plugin/compare/2.5.0...HEAD
[Unreleased]: https://github.com/sensu-plugins/sensu-plugin/compare/2.6.1...HEAD
[2.6.1]: https://github.com/sensu-plugins/sensu-plugin/compare/2.6.0...2.6.1
[2.6.0]: https://github.com/sensu-plugins/sensu-plugin/compare/2.5.0...2.6.0
[2.5.0]: https://github.com/sensu-plugins/sensu-plugin/compare/2.4.0...2.5.0
[2.4.0]: https://github.com/sensu-plugins/sensu-plugin/compare/2.3.0...2.4.0
[2.3.0]: https://github.com/sensu-plugins/sensu-plugin/compare/2.2.0...2.3.0
Expand Down
51 changes: 0 additions & 51 deletions lib/sensu-handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,57 +99,6 @@ def bail(msg)
exit 0
end

# Override API settings (for testing purposes)
#
# @param api_settings [Hash]
# @return [Hash]
def api_settings=(api_settings)
@api_settings = api_settings
end

# Return a hash of API settings derived first from ENV['SENSU_API_URL'] if set,
# then Sensu config `api` scope if configured, and finally falling back to
# to ipv4 localhost address on default API port.
#
# @return [Hash]
def api_settings
return @api_settings if @api_settings
if ENV['SENSU_API_URL']
uri = URI(ENV['SENSU_API_URL'])
ssl = uri.scheme == 'https' ? {} : nil
@api_settings = {
'ssl' => ssl,
'host' => uri.host,
'port' => uri.port,
'user' => uri.user,
'password' => uri.password
}
else
@api_settings = settings['api'] || {}
@api_settings['host'] ||= '127.0.0.1'
@api_settings['port'] ||= 4567
end
@api_settings
end

def api_request(method, path, &_blk)
if api_settings.nil?
raise 'api.json settings not found.'
end
use_ssl = api_settings['ssl'].is_a?(Hash) ||
api_settings['host'].start_with?('https')
hostname = api_settings['host'].gsub(/https?:\/\//, '')
req = net_http_req_class(method).new(path)
if api_settings['user'] && api_settings['password']
req.basic_auth(api_settings['user'], api_settings['password'])
end
yield(req) if block_given?
res = Net::HTTP.start(hostname, api_settings['port'], use_ssl: use_ssl) do |http|
http.request(req)
end
res
end

def filter_disabled
bail 'alert disabled' if @event['check']['alert'] == false
end
Expand Down
2 changes: 1 addition & 1 deletion lib/sensu-plugin.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Sensu
module Plugin
VERSION = '2.5.0'.freeze
VERSION = '2.6.1'.freeze
EXIT_CODES = {
'OK' => 0,
'WARNING' => 1,
Expand Down
82 changes: 81 additions & 1 deletion lib/sensu-plugin/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Sensu
module Plugin
module Utils
module Utils # rubocop:disable Metrics/ModuleLength
def config_files
if ENV['SENSU_LOADED_TEMPFILE'] && File.file?(ENV['SENSU_LOADED_TEMPFILE'])
IO.read(ENV['SENSU_LOADED_TEMPFILE']).split(':')
Expand Down Expand Up @@ -46,6 +46,86 @@ def net_http_req_class(method)
end
end

# Override API settings (for testing purposes)
#
# @param api_settings [Hash]
# @return [Hash]
def api_settings=(api_settings)
@api_settings = api_settings
end

# Return a hash of API settings derived first from ENV['SENSU_API_URL'] if set,
# then Sensu config `api` scope if configured, and finally falling back to
# to ipv4 localhost address on default API port.
#
# @return [Hash]
def api_settings
return @api_settings if @api_settings
if ENV['SENSU_API_URL']
uri = URI(ENV['SENSU_API_URL'])
ssl = uri.scheme == 'https' ? {} : nil
@api_settings = {
'ssl' => ssl,
'host' => uri.host,
'port' => uri.port,
'user' => uri.user,
'password' => uri.password
}
else
@api_settings = settings['api'] || {}
@api_settings['host'] ||= '127.0.0.1'
@api_settings['port'] ||= 4567
end
@api_settings
end

def api_request(method, path, &_blk)
if api_settings.nil?
raise 'api.json settings not found.'
end
use_ssl = api_settings['ssl'].is_a?(Hash) ||
api_settings['host'].start_with?('https')
hostname = api_settings['host'].gsub(/https?:\/\//, '')
req = net_http_req_class(method).new(path)
if api_settings['user'] && api_settings['password']
req.basic_auth(api_settings['user'], api_settings['password'])
end
yield(req) if block_given?
res = Net::HTTP.start(hostname, api_settings['port'], use_ssl: use_ssl) do |http|
http.request(req)
end
res
end

# Use API query parameters to paginate HTTP GET requests,
# iterating over the results until an empty set is returned.
#
# @param path [String]
# @param options [Hash]
# @return [Array]

def paginated_get(path, options = {})
limit = options.fetch('limit', 500)
offset = 0
results = []
loop do
query_path = "#{path}?limit=#{limit}&offset=#{offset}"
response = api_request(:GET, query_path)
unless response.is_a?(Net::HTTPOK)
unknown("Non-OK response from API query: #{get_uri(query_path)}")
end
data = JSON.parse(response.body)
# when the data is empty, we have hit the end
break if data.empty?
# If API lacks pagination support, it will
# return same data on subsequent iterations
break if results.any? { |r| r == data }
results << data
offset += limit
end
results.flatten
end

def deep_merge(hash_one, hash_two)
merged = hash_one.dup
hash_two.each do |key, value|
Expand Down
40 changes: 40 additions & 0 deletions test/handle_api_request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ class TestHandleAPIRequest < MiniTest::Test

Sensu::Handler.disable_autorun

def sample_check_result
{
client: 'sensu',
check: {
handler: 'keepalive',
name: 'keepalive',
issued: 1_534_373_016,
executed: 1_534_373_016,
output: 'Keepalive sent from client 4 seconds ago',
status: 0,
type: 'standard',
history: [0]
}
}
end

def test_http_request
stub_request(:get, 'http://127.0.0.1:4567/foo').to_return(status: 200, body: '', headers: {})

Expand All @@ -16,6 +32,30 @@ def test_http_request
assert_equal(response.code, '200')
end

def test_http_paginated_get
result_two = sample_check_result.dup
result_two[:client] = 'haproxy01'
result_two[:name] = 'check_haproxy'
result_two[:output] = 'haproxy is fubar'
result_two[:status] = 2

stub_request(:get, 'http://127.0.0.1:4567/results?limit=1&offset=0')
.to_return(status: 200, headers: {}, body: JSON.dump([sample_check_result]))

stub_request(:get, 'http://127.0.0.1:4567/results?limit=1&offset=1')
.to_return(status: 200, headers: {}, body: JSON.dump([result_two]))

stub_request(:get, 'http://127.0.0.1:4567/results?limit=1&offset=2')
.to_return(status: 200, headers: {}, body: JSON.dump([]))

handler = Sensu::Handler.new([])
response = handler.paginated_get('/results', 'limit' => 1)

# we expect the combined results to be an array containing two instances of the sample check result
combined_results = JSON.parse("[ #{JSON.dump(sample_check_result)} , #{JSON.dump(result_two)} ]")
assert_equal(response, combined_results)
end

def test_https_request
stub_request(:get, 'https://127.0.0.1:4567/foo').to_return(status: 200, body: '', headers: {})

Expand Down