diff --git a/lib/vmpooler/api.rb b/lib/vmpooler/api.rb index 7d72ec6d6..eb856fc3d 100644 --- a/lib/vmpooler/api.rb +++ b/lib/vmpooler/api.rb @@ -3,7 +3,7 @@ module Vmpooler class API < Sinatra::Base # Load API components - %w[helpers dashboard reroute v1 request_logger].each do |lib| + %w[helpers dashboard reroute v1 request_logger healthcheck].each do |lib| require "vmpooler/api/#{lib}" end # Load dashboard components @@ -40,6 +40,10 @@ def self.execute(torun, config, redis, metrics, logger) require 'prometheus/middleware/exporter' use Vmpooler::Metrics::Promstats::CollectorMiddleware, metrics_prefix: "#{metrics.prometheus_prefix}_http" use Prometheus::Middleware::Exporter, path: metrics.prometheus_endpoint + # Note that a user may want to use this check without prometheus + # However, prometheus setup includes the web server which is required for this check + # At this time prometheus is a requirement of using the health check on manager + use Vmpooler::API::Healthcheck end if torun.include? :api diff --git a/lib/vmpooler/api/healthcheck.rb b/lib/vmpooler/api/healthcheck.rb new file mode 100644 index 000000000..50da734c5 --- /dev/null +++ b/lib/vmpooler/api/healthcheck.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Vmpooler + class API + class Healthcheck < Sinatra::Base + get '/healthcheck/?' do + content_type :json + + status 200 + JSON.pretty_generate({ 'ok' => true }) + end + end + end +end diff --git a/spec/integration/api/healthcheck_spec.rb b/spec/integration/api/healthcheck_spec.rb new file mode 100644 index 000000000..ecce07ec2 --- /dev/null +++ b/spec/integration/api/healthcheck_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' +require 'rack/test' + +describe Vmpooler::API::Healthcheck do + include Rack::Test::Methods + + def app() + Vmpooler::API + end + + # Added to ensure no leakage in rack state from previous tests. + # Removes all routes, filters, middleware and extension hooks from the current class + # https://rubydoc.info/gems/sinatra/Sinatra/Base#reset!-class_method + before(:each) do + app.reset! + end + + let(:config) { + { + config: { + 'site_name' => 'test pooler', + 'vm_lifetime_auth' => 2, + }, + pools: [ + {'name' => 'pool1', 'size' => 5, 'alias' => ['poolone', 'poolun']}, + {'name' => 'pool2', 'size' => 10}, + {'name' => 'pool3', 'size' => 10, 'alias' => 'NotArray'} + ] + } + } + + let(:current_time) { Time.now } + + let(:metrics) { + double("metrics") + } + + before(:each) do + expect(app).to receive(:run!).once + expect(metrics).to receive(:setup_prometheus_metrics) + expect(metrics).to receive(:prometheus_prefix) + expect(metrics).to receive(:prometheus_endpoint) + app.execute([:api], config, redis, metrics, nil) + app.settings.set :config, auth: false + end + + describe '/healthcheck' do + it 'returns OK' do + get "/healthcheck" + expect(last_response.header['Content-Type']).to eq('application/json') + expect(last_response.status).to eq(200) + result = JSON.parse(last_response.body) + expect(result).to eq({'ok' => true}) + end + end +end