This commit is contained in:
Scott Schneider 2015-04-21 17:01:08 +00:00
commit fb80cf25d2
4 changed files with 197 additions and 18 deletions

View file

@ -4,6 +4,35 @@ module Vmpooler
module Helpers module Helpers
def authenticate(auth, username_str, password_str)
case auth['provider']
when 'ldap'
require 'rubygems'
require 'net/ldap'
ldap = Net::LDAP.new(
:host => auth[:ldap]['host'],
:port => auth[:ldap]['port'] || 389,
:encryption => {
:method => :start_tls,
:tls_options => { :ssl_version => 'TLSv1' }
},
:base => auth[:ldap]['base'],
:auth => {
:method => :simple,
:username => "#{auth[:ldap]['user_object']}=#{username_str},#{auth[:ldap]['base']}",
:password => password_str
}
)
if ldap.bind
return true
end
end
return false
end
def mean(list) def mean(list)
s = list.map(&:to_f).reduce(:+).to_f s = list.map(&:to_f).reduce(:+).to_f
(s > 0 && list.length > 0) ? s / list.length.to_f : 0 (s > 0 && list.length > 0) ? s / list.length.to_f : 0

View file

@ -11,6 +11,18 @@ module Vmpooler
call env.merge("PATH_INFO" => "/api/v#{api_version}/summary") call env.merge("PATH_INFO" => "/api/v#{api_version}/summary")
end end
post '/token/?' do
call env.merge("PATH_INFO" => "/api/v#{api_version}/token")
end
get '/token/:token/?' do
call env.merge("PATH_INFO" => "/api/v#{api_version}/token/#{params[:token]}")
end
delete '/token/:token/?' do
call env.merge("PATH_INFO" => "/api/v#{api_version}/token/#{params[:token]}")
end
get '/vm/?' do get '/vm/?' do
call env.merge("PATH_INFO" => "/api/v#{api_version}/vm") call env.merge("PATH_INFO" => "/api/v#{api_version}/vm")
end end

View file

@ -173,6 +173,69 @@ module Vmpooler
JSON.pretty_generate(result) JSON.pretty_generate(result)
end end
get "#{api_prefix}/token/:token/?" do
content_type :json
result = { 'ok' => false }
Vmpooler::API.settings.config[:auth] ? status(401) : status(404)
result[params[:token]] = Vmpooler::API.settings.redis.hgetall('vmpooler__token__' + params[:token])
if Vmpooler::API.settings.config[:auth] and result[params[:token]]['timestamp']
status(200)
result['ok'] = true
else
result.delete(params[:token])
end
JSON.pretty_generate(result)
end
delete "#{api_prefix}/token/:token/?" do
content_type :json
result = { 'ok' => false }
Vmpooler::API.settings.config[:auth] ? status(401) : status(404)
if Vmpooler::API.settings.config[:auth] and Vmpooler::API.settings.redis.del('vmpooler__token__' + params[:token])
status(200)
result['ok'] = true
end
JSON.pretty_generate(result)
end
post "#{api_prefix}/token" do
content_type :json
result = { 'ok' => false }
Vmpooler::API.settings.config[:auth] ? status(401) : status(404)
jdata = JSON.parse(request.body.read)
if Vmpooler::API.settings.config[:auth] and jdata['username'] and jdata['password']
if authenticate(
Vmpooler::API.settings.config[:auth],
jdata['username'].to_s,
jdata['password'].to_s
)
status(200)
result['ok'] = true
o = [('a'..'z'), ('0'..'9')].map(&:to_a).flatten
result['token'] = o[rand(25)] + (0...31).map { o[rand(o.length)] }.join
Vmpooler::API.settings.redis.hset('vmpooler__token__' + result['token'], 'user', jdata['username'].to_s)
Vmpooler::API.settings.redis.hset('vmpooler__token__' + result['token'], 'timestamp', Time.now)
end
end
JSON.pretty_generate(result)
end
get "#{api_prefix}/vm/?" do get "#{api_prefix}/vm/?" do
content_type :json content_type :json
@ -229,13 +292,13 @@ module Vmpooler
else else
result[key]['ok'] = false ## result[key]['ok'] = false ##
status 503 status(503)
result['ok'] = false result['ok'] = false
end end
end end
end end
else else
status 503 status(503)
result['ok'] = false result['ok'] = false
end end
@ -291,12 +354,12 @@ module Vmpooler
else else
result[template]['ok'] = false ## result[template]['ok'] = false ##
status 503 status(503)
result['ok'] = false result['ok'] = false
end end
end end
else else
status 503 status(503)
result['ok'] = false result['ok'] = false
end end
@ -310,15 +373,14 @@ module Vmpooler
get "#{api_prefix}/vm/:hostname/?" do get "#{api_prefix}/vm/:hostname/?" do
content_type :json content_type :json
result = {} result = { 'ok' => false }
status 404 status(404)
result['ok'] = false
params[:hostname] = hostname_shorten(params[:hostname], Vmpooler::API.settings.config[:config]['domain']) params[:hostname] = hostname_shorten(params[:hostname], Vmpooler::API.settings.config[:config]['domain'])
if Vmpooler::API.settings.redis.exists('vmpooler__vm__' + params[:hostname]) if Vmpooler::API.settings.redis.exists('vmpooler__vm__' + params[:hostname])
status 200 status(200)
result['ok'] = true result['ok'] = true
rdata = Vmpooler::API.settings.redis.hgetall('vmpooler__vm__' + params[:hostname]) rdata = Vmpooler::API.settings.redis.hgetall('vmpooler__vm__' + params[:hostname])
@ -352,10 +414,9 @@ module Vmpooler
delete "#{api_prefix}/vm/:hostname/?" do delete "#{api_prefix}/vm/:hostname/?" do
content_type :json content_type :json
result = {} result = { 'ok' => false }
status 404 status(404)
result['ok'] = false
params[:hostname] = hostname_shorten(params[:hostname], Vmpooler::API.settings.config[:config]['domain']) params[:hostname] = hostname_shorten(params[:hostname], Vmpooler::API.settings.config[:config]['domain'])
@ -364,7 +425,7 @@ module Vmpooler
Vmpooler::API.settings.redis.srem('vmpooler__running__' + pool['name'], params[:hostname]) Vmpooler::API.settings.redis.srem('vmpooler__running__' + pool['name'], params[:hostname])
Vmpooler::API.settings.redis.sadd('vmpooler__completed__' + pool['name'], params[:hostname]) Vmpooler::API.settings.redis.sadd('vmpooler__completed__' + pool['name'], params[:hostname])
status 200 status(200)
result['ok'] = true result['ok'] = true
end end
end end
@ -377,10 +438,9 @@ module Vmpooler
failure = false failure = false
result = {} result = { 'ok' => false }
status 404 status(404)
result['ok'] = false
params[:hostname] = hostname_shorten(params[:hostname], Vmpooler::API.settings.config[:config]['domain']) params[:hostname] = hostname_shorten(params[:hostname], Vmpooler::API.settings.config[:config]['domain'])
@ -388,7 +448,7 @@ module Vmpooler
begin begin
jdata = JSON.parse(request.body.read) jdata = JSON.parse(request.body.read)
rescue rescue
status 400 status(400)
return JSON.pretty_generate(result) return JSON.pretty_generate(result)
end end
@ -409,7 +469,7 @@ module Vmpooler
end end
if failure if failure
status 400 status(400)
else else
jdata.each do |param, arg| jdata.each do |param, arg|
case param case param
@ -424,7 +484,7 @@ module Vmpooler
end end
end end
status 200 status(200)
result['ok'] = true result['ok'] = true
end end
end end

View file

@ -0,0 +1,78 @@
require 'spec_helper'
require 'rack/test'
describe Vmpooler::API::V1 do
include Rack::Test::Methods
def app()
# because of how Vmpooler::API.settings are used
# we need to test the whole thing...
Vmpooler::API
end
describe 'tokens' do
let(:redis) { double('redis') }
let(:config) {
{
config: {'site_name' => 'test pooler'},
auth: {exists: 1}
}
}
let(:prefix) { '/api/v1' }
before do
$config = config
app.settings.set :config, config
app.settings.set :redis, redis
app.settings.set :environment, :test
end
describe 'GET /token/:token' do
context 'valid tokens' do
before do
allow(redis).to receive(:exists).and_return 1
allow(redis).to receive(:hgetall).and_return 'atoken'
end
it 'sets key to passed value (:token)' do
get "#{prefix}/token/this"
expect(last_response).to be_ok
expect(last_response.body).to eq(JSON.pretty_generate({'ok' => true, 'this' => 'atoken'}))
expect(last_response.header['Content-Type']).to eq('application/json')
get "#{prefix}/token/that"
expect(last_response).to be_ok
expect(last_response.body).to eq(JSON.pretty_generate({'ok' => true, 'that' => 'atoken'}))
expect(last_response.header['Content-Type']).to eq('application/json')
end
end
end
describe 'DELETE /token/:token' do
context 'valid tokens' do
before do
allow(redis).to receive(:exists).with(String).and_return 1
allow(redis).to receive(:del)
end
it 'deletes the key' do
expect(redis).to receive(:del)
delete "#{prefix}/token/this"
expect(last_response).to be_ok
expect(last_response.header['Content-Type']).to eq('application/json')
expect(last_response.body).to eq(JSON.pretty_generate({'ok' => true}))
end
end
end
end
end