Skip to content

Commit

Permalink
Merge pull request #124 from pulibrary/solr-check
Browse files Browse the repository at this point in the history
Allowing a specific solr collection to be monitored
  • Loading branch information
lbeder authored Aug 22, 2024
2 parents 51cca58 + 55a4159 commit 84febf5
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ Please note that `url` or `connection` can't be used at the same time.
### Solr

* `url`: the URL used to connect to your Solr instance - must be a string. You can also use `url` to explicitly configure authentication (e.g., `'https://user:pass@example.solr.com:8983/'`)
* `collection`: An optional parameter used to connect to your specific Solr collection - must be a string. By setting this parameter the code will check the status of this individual collection in your Solr instance instead of just the status of the overall Solr instance

### Adding a Custom Provider

Expand Down
38 changes: 32 additions & 6 deletions lib/health_monitor/providers/solr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ class SolrException < StandardError; end
class Solr < Base
class Configuration < Base::Configuration
DEFAULT_URL = nil
attr_accessor :url
DEFAULT_COLLECTION = nil
attr_accessor :url, :collection

def initialize(provider)
super(provider)

@url = DEFAULT_URL
@collection = DEFAULT_COLLECTION
end
end

Expand All @@ -31,6 +33,22 @@ def configuration_class
end

def check_solr_connection!
if configuration.collection
check_solr_collection!
else
check_solr_uri!
end
end

def check_solr_collection!
response = solr_response(uri: collection_uri)
json = JSON.parse(response.body) if response.code == '200'
return if response.is_a?(Net::HTTPSuccess) && json['status'].casecmp?('OK')

raise "The Solr collection has an invalid status #{collection_uri}"
end

def check_solr_uri!
json = JSON.parse(solr_response.body)
raise "The solr has an invalid status #{status_uri}" if json['responseHeader']['status'] != 0
end
Expand All @@ -44,16 +62,24 @@ def status_uri
end
end

def solr_request
def collection_uri
@collection_uri ||= begin
uri = URI(configuration.url)
uri.path = "/solr/#{configuration.collection}/admin/ping"
uri
end
end

def solr_request(uri: status_uri)
@solr_request ||= begin
req = Net::HTTP::Get.new(status_uri)
req.basic_auth(status_uri.user, status_uri.password) if status_uri.user && status_uri.password
req = Net::HTTP::Get.new(uri)
req.basic_auth(uri.user, uri.password) if uri.user && uri.password
req
end
end

def solr_response
Net::HTTP.start(status_uri.hostname, status_uri.port) { |http| http.request(solr_request) }
def solr_response(uri: status_uri)
Net::HTTP.start(status_uri.hostname, status_uri.port) { |http| http.request(solr_request(uri: uri)) }
end
end
end
Expand Down
113 changes: 113 additions & 0 deletions spec/lib/health_monitor/providers/solr_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,100 @@
end
end
end

context 'with a specified collection' do
let(:solr_collection_config) { 'example-collection' }

before do
subject.request = test_request
subject.configure do |config|
config.url = solr_url_config
config.collection = solr_collection_config
end
Providers.stub_solr_collection(solr_collection_config)
end

context 'with a standard connection' do
it 'checks against the configured solr url' do
subject.check!
expect(Providers.stub_solr_collection(solr_collection_config)).to have_been_requested
end

it 'succesfully checks' do
expect {
subject.check!
}.not_to raise_error
end

context 'when failing' do
let(:solr_failure) { Providers.stub_solr_collection(solr_collection_config, body: '', status: 404) }

before do
solr_failure
end

it 'fails check!' do
expect {
subject.check!
}.to raise_error(HealthMonitor::Providers::SolrException)
end

it 'checks against the configured solr url' do
expect {
subject.check!
}.to raise_error(HealthMonitor::Providers::SolrException)
expect(solr_failure).to have_been_requested
end
end
end

context 'with a configured url that includes a path' do
let(:solr_url_config) { 'http://www.example-solr.com:8983/solr/blacklight-core-development' }

it 'checks against the configured solr url' do
subject.check!
expect(Providers.stub_solr_collection(solr_collection_config)).to have_been_requested
end
end

context 'with a connection with authentication' do
let(:solr_url_config) { 'http://solr:SolrRocks@localhost:8888' }

before { Providers.stub_solr_collection_with_auth(solr_collection_config) }

it 'checks against the configured solr url' do
subject.check!
expect(Providers.stub_solr_collection_with_auth(solr_collection_config)).to have_been_requested
end

it 'succesfully checks' do
expect {
subject.check!
}.not_to raise_error
end

context 'when failing' do
let(:provider_failure) { Providers.stub_solr_collection_with_auth(solr_collection_config, status: 404, body: '') }

before do
provider_failure
end

it 'fails check!' do
expect {
subject.check!
}.to raise_error(HealthMonitor::Providers::SolrException)
end

it 'checks against the configured solr url' do
expect {
subject.check!
}.to raise_error(HealthMonitor::Providers::SolrException)
expect(provider_failure).to have_been_requested
end
end
end
end
end

describe '#configure' do
Expand All @@ -109,6 +203,7 @@
end

let(:url) { 'solr://user:password@fake.solr.com:8983/' }
let(:collection) { 'my-collection' }

it 'url can be configured' do
expect {
Expand All @@ -117,5 +212,23 @@
end
}.to change { subject.configuration.url }.to(url)
end

it 'collection can be configured' do
expect {
subject.configure do |config|
config.collection = collection
end
}.to change { subject.configuration.collection }.to(collection)
end

it 'url and collection can be configured' do
expect {
subject.configure do |config|
config.url = url
config.collection = collection
end
}.to change { subject.configuration.collection }.to(collection)
.and change { subject.configuration.url }.to(url)
end
end
end
11 changes: 11 additions & 0 deletions spec/support/providers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ def stub_solr_failure
)
end

def stub_solr_collection(collection, status: 200, body: { responseHeader: { status: 0 }, status: 'OK' }.to_json)
WebMock.stub_request(:get, "http://www.example-solr.com:8983/solr/#{collection}/admin/ping")
.to_return(body: body, headers: { 'Content-Type' => 'text/json' }, status: status)
end

def stub_solr_with_auth
WebMock.stub_request(:get, 'http://localhost:8888/solr/admin/cores?action=STATUS')
.with(headers: { 'Authorization' => 'Basic c29scjpTb2xyUm9ja3M=', 'Host' => 'localhost:8888' })
Expand All @@ -114,4 +119,10 @@ def stub_solr_failure_with_auth
.with(headers: { 'Authorization' => 'Basic c29scjpTb2xyUm9ja3M=', 'Host' => 'localhost:8888' })
.to_return(body: { responseHeader: { status: 500 } }.to_json, headers: { 'Content-Type' => 'text/json' })
end

def stub_solr_collection_with_auth(collection, status: 200, body: { responseHeader: { status: 0 }, status: 'OK' }.to_json)
WebMock.stub_request(:get, "http://localhost:8888/solr/#{collection}/admin/ping")
.with(headers: { 'Authorization' => 'Basic c29scjpTb2xyUm9ja3M=', 'Host' => 'localhost:8888' })
.to_return(body: body, headers: { 'Content-Type' => 'text/json' }, status: status)
end
end

0 comments on commit 84febf5

Please sign in to comment.