(POOLER-93) Extend API endpoint to provide just what is needed

The status endpoint provides a lot of statistics. This commit extends it
by supporting a query parameter called 'view' which may contain one or
multiple comma separated names for the top-level statistics returned
in the JSON response. status is always returned.
Optional elements are capacity,queue,clone,boot,pools
Everything is returned when 'view' is not specified, which is
backwards compatible with the current behavior.
This commit is contained in:
Samuel Beaulieu 2017-10-19 17:25:15 -05:00
parent abdc86f164
commit 96541729fb
2 changed files with 96 additions and 6 deletions

View file

@ -176,23 +176,33 @@ module Vmpooler
# ], # ],
# "uptime": 179585.9 # "uptime": 179585.9
# } # }
#
# If the query parameter 'view' is provided, it will be used to select which top level
# element to compute and return. Select them by specifying them in a comma separated list.
# For example /status?view=capacity,boot
# would return only the "capacity" and "boot" statistics. "status" is always returned
get "#{api_prefix}/status/?" do get "#{api_prefix}/status/?" do
content_type :json content_type :json
if params[:view]
views = params[:view].split(",")
end
result = { result = {
pools: {},
status: { status: {
ok: true, ok: true,
message: 'Battle station fully armed and operational.' message: 'Battle station fully armed and operational.'
} }
} }
result[:capacity] = get_capacity_metrics(pools, backend) result[:capacity] = get_capacity_metrics(pools, backend) unless views and not views.include?("capacity")
result[:queue] = get_queue_metrics(pools, backend) result[:queue] = get_queue_metrics(pools, backend) unless views and not views.include?("queue")
result[:clone] = get_task_metrics(backend, 'clone', Date.today.to_s) result[:clone] = get_task_metrics(backend, 'clone', Date.today.to_s) unless views and not views.include?("clone")
result[:boot] = get_task_metrics(backend, 'boot', Date.today.to_s) result[:boot] = get_task_metrics(backend, 'boot', Date.today.to_s) unless views and not views.include?("boot")
# Check for empty pools # Check for empty pools
result[:pools] = {} unless views and not views.include?("pools")
pools.each do |pool| pools.each do |pool|
# REMIND: move this out of the API and into the back-end # REMIND: move this out of the API and into the back-end
ready = backend.scard('vmpooler__ready__' + pool['name']).to_i ready = backend.scard('vmpooler__ready__' + pool['name']).to_i
@ -220,7 +230,7 @@ module Vmpooler
result[:status][:ok] = false result[:status][:ok] = false
result[:status][:message] = "Found #{result[:status][:empty].length} empty pools." result[:status][:message] = "Found #{result[:status][:empty].length} empty pools."
end end
end end unless views and not views.include?("pools")
result[:status][:uptime] = (Time.now - Vmpooler::API.settings.config[:uptime]).round(1) if Vmpooler::API.settings.config[:uptime] result[:status][:uptime] = (Time.now - Vmpooler::API.settings.config[:uptime]).round(1) if Vmpooler::API.settings.config[:uptime]

View file

@ -118,5 +118,85 @@ describe Vmpooler::API::V1 do
expect(result["status"]["empty"].sort).to eq(["pool1", "pool2", "pool3"]) expect(result["status"]["empty"].sort).to eq(["pool1", "pool2", "pool3"])
end end
end end
describe 'GET /status with view query parameter' do
it 'returns capacity when specified' do
get "#{prefix}/status?view=capacity"
# of course /status doesn't conform to the weird standard everything else uses...
expect(last_response.header['Content-Type']).to eq('application/json')
result = JSON.parse(last_response.body)
expect(result["capacity"]).to_not be(nil)
expect(result["queue"]).to be(nil)
expect(result["clone"]).to be(nil)
expect(result["boot"]).to be(nil)
expect(result["pools"]).to be(nil)
expect(result["status"]).to_not be(nil)
end
it 'returns pools and queue when specified' do
get "#{prefix}/status?view=pools,queue"
# of course /status doesn't conform to the weird standard everything else uses...
expect(last_response.header['Content-Type']).to eq('application/json')
result = JSON.parse(last_response.body)
expect(result["capacity"]).to be(nil)
expect(result["queue"]).to_not be(nil)
expect(result["clone"]).to be(nil)
expect(result["boot"]).to be(nil)
expect(result["pools"]).to_not be(nil)
expect(result["status"]).to_not be(nil)
end
it 'does nothing with invalid view names' do
get "#{prefix}/status?view=clone,boot,invalidThingToView"
# of course /status doesn't conform to the weird standard everything else uses...
expect(last_response.header['Content-Type']).to eq('application/json')
result = JSON.parse(last_response.body)
expect(result["capacity"]).to be(nil)
expect(result["queue"]).to be(nil)
expect(result["clone"]).to_not be(nil)
expect(result["boot"]).to_not be(nil)
expect(result["pools"]).to be(nil)
expect(result["status"]).to_not be(nil)
end
it 'returns everything when view is not specified' do
get "#{prefix}/status"
# of course /status doesn't conform to the weird standard everything else uses...
expect(last_response.header['Content-Type']).to eq('application/json')
result = JSON.parse(last_response.body)
expect(result["capacity"]).to_not be(nil)
expect(result["queue"]).to_not be(nil)
expect(result["clone"]).to_not be(nil)
expect(result["boot"]).to_not be(nil)
expect(result["pools"]).to_not be(nil)
expect(result["status"]).to_not be(nil)
end
it 'returns everything when view is alone' do
get "#{prefix}/status?view"
# of course /status doesn't conform to the weird standard everything else uses...
expect(last_response.header['Content-Type']).to eq('application/json')
result = JSON.parse(last_response.body)
expect(result["capacity"]).to_not be(nil)
expect(result["queue"]).to_not be(nil)
expect(result["clone"]).to_not be(nil)
expect(result["boot"]).to_not be(nil)
expect(result["pools"]).to_not be(nil)
expect(result["status"]).to_not be(nil)
end
it 'returns status only when view is empty' do
get "#{prefix}/status?view="
# of course /status doesn't conform to the weird standard everything else uses...
expect(last_response.header['Content-Type']).to eq('application/json')
result = JSON.parse(last_response.body)
expect(result["capacity"]).to be(nil)
expect(result["queue"]).to be(nil)
expect(result["clone"]).to be(nil)
expect(result["boot"]).to be(nil)
expect(result["pools"]).to be(nil)
expect(result["status"]).to_not be(nil)
end
end
end end
end end