mirror of
https://github.com/puppetlabs/vmpooler.git
synced 2026-01-26 01:58:41 -05:00
This is a re-architect of the vmpooler initialisation code to: 1. Allow an API service for both manager and the api 2. Add the Prometheus endpoints to the web service. Needed to change the way the Rack Service is started as instantiating using ".New" leads to a failure to initialise the http Stats collection. 3. Selectively load the pooler api and/or Prometheus endpoints. 4. Rework API Spec tests for revised API loading. Needed to tidy up the initialisation and perform a reset! after each test to avoid "leaks" and dependencies between the tests.
352 lines
11 KiB
Ruby
352 lines
11 KiB
Ruby
require 'spec_helper'
|
|
require 'rack/test'
|
|
|
|
def has_set_tag?(vm, tag, value)
|
|
value == redis.hget("vmpooler__vm__#{vm}", "tag:#{tag}")
|
|
end
|
|
|
|
describe Vmpooler::API::V1 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
|
|
|
|
describe '/vm/:hostname' do
|
|
let(:prefix) { '/api/v1' }
|
|
let(:metrics) { Vmpooler::DummyStatsd.new }
|
|
|
|
let(:config) {
|
|
{
|
|
config: {
|
|
'site_name' => 'test pooler',
|
|
'vm_lifetime_auth' => 2,
|
|
|
|
},
|
|
pools: [
|
|
{'name' => 'pool1', 'size' => 5},
|
|
{'name' => 'pool2', 'size' => 10}
|
|
],
|
|
alias: { 'poolone' => 'pool1' },
|
|
auth: false
|
|
}
|
|
}
|
|
|
|
let(:current_time) { Time.now }
|
|
|
|
before(:each) do
|
|
expect(app).to receive(:run!).once
|
|
app.execute(['api'], config, redis, metrics)
|
|
create_token('abcdefghijklmnopqrstuvwxyz012345', 'jdoe', current_time)
|
|
end
|
|
|
|
describe 'PUT /vm/:hostname' do
|
|
it 'allows tags to be set' do
|
|
create_vm('testhost', redis)
|
|
put "#{prefix}/vm/testhost", '{"tags":{"tested_by":"rspec"}}'
|
|
expect_json(ok = true, http = 200)
|
|
|
|
expect has_set_tag?('testhost', 'tested_by', 'rspec')
|
|
end
|
|
|
|
it 'skips empty tags' do
|
|
create_vm('testhost', redis)
|
|
put "#{prefix}/vm/testhost", '{"tags":{"tested_by":""}}'
|
|
expect_json(ok = true, http = 200)
|
|
|
|
expect !has_set_tag?('testhost', 'tested_by', '')
|
|
end
|
|
|
|
it 'does not set tags if request body format is invalid' do
|
|
create_vm('testhost', redis)
|
|
put "#{prefix}/vm/testhost", '{"tags":{"tested"}}'
|
|
expect_json(ok = false, http = 400)
|
|
|
|
expect !has_set_tag?('testhost', 'tested', '')
|
|
end
|
|
|
|
context '(allowed_tags configured)' do
|
|
it 'fails if specified tag is not in allowed_tags array' do
|
|
app.settings.set :config,
|
|
{ :config => { 'allowed_tags' => ['created_by', 'project', 'url'] } }
|
|
|
|
create_vm('testhost', redis)
|
|
|
|
put "#{prefix}/vm/testhost", '{"tags":{"created_by":"rspec","tested_by":"rspec"}}'
|
|
expect_json(ok = false, http = 400)
|
|
|
|
expect !has_set_tag?('testhost', 'tested_by', 'rspec')
|
|
end
|
|
end
|
|
|
|
context '(tagfilter configured)' do
|
|
before(:each) do
|
|
app.settings.set :config, tagfilter: { 'url' => '(.*)\/' }
|
|
end
|
|
|
|
it 'correctly filters tags' do
|
|
create_vm('testhost', redis)
|
|
|
|
put "#{prefix}/vm/testhost", '{"tags":{"url":"foo.com/something.html"}}'
|
|
expect_json(ok = true, http = 200)
|
|
|
|
expect has_set_tag?('testhost', 'url', 'foo.com')
|
|
end
|
|
|
|
it "doesn't eat tags not matching filter" do
|
|
create_vm('testhost', redis)
|
|
put "#{prefix}/vm/testhost", '{"tags":{"url":"foo.com"}}'
|
|
expect_json(ok = true, http = 200)
|
|
|
|
expect has_set_tag?('testhost', 'url', 'foo.com')
|
|
end
|
|
end
|
|
|
|
context '(auth not configured)' do
|
|
before(:each) do
|
|
app.settings.set :config, auth: false
|
|
end
|
|
|
|
it 'allows VM lifetime to be modified without a token' do
|
|
create_vm('testhost', redis)
|
|
|
|
put "#{prefix}/vm/testhost", '{"lifetime":"1"}'
|
|
expect_json(ok = true, http = 200)
|
|
|
|
vm = fetch_vm('testhost')
|
|
expect(vm['lifetime'].to_i).to eq(1)
|
|
end
|
|
|
|
it 'does not allow a lifetime to be 0' do
|
|
create_vm('testhost', redis)
|
|
|
|
put "#{prefix}/vm/testhost", '{"lifetime":"0"}'
|
|
expect_json(ok = false, http = 400)
|
|
|
|
vm = fetch_vm('testhost')
|
|
expect(vm['lifetime']).to be_nil
|
|
end
|
|
|
|
it 'does not enforce a lifetime' do
|
|
create_vm('testhost', redis)
|
|
|
|
put "#{prefix}/vm/testhost", '{"lifetime":"20000"}'
|
|
expect_json(ok = true, http = 200)
|
|
|
|
vm = fetch_vm('testhost')
|
|
expect(vm['lifetime']).to eq("20000")
|
|
end
|
|
|
|
it 'does not allow a lifetime to be initially past config max_lifetime_upper_limit' do
|
|
app.settings.set :config,
|
|
{ :config => { 'max_lifetime_upper_limit' => 168 } }
|
|
create_vm('testhost', redis)
|
|
|
|
put "#{prefix}/vm/testhost", '{"lifetime":"200"}'
|
|
expect_json(ok = false, http = 400)
|
|
|
|
vm = fetch_vm('testhost')
|
|
expect(vm['lifetime']).to be_nil
|
|
end
|
|
|
|
# it 'does not allow a lifetime to be extended past config 168' do
|
|
# app.settings.set :config,
|
|
# { :config => { 'max_lifetime_upper_limit' => 168 } }
|
|
# create_vm('testhost', redis)
|
|
#
|
|
# set_vm_data('testhost', "checkout", (Time.now - (69*60*60)), redis)
|
|
# puts redis.hget("vmpooler__vm__testhost", 'checkout')
|
|
# put "#{prefix}/vm/testhost", '{"lifetime":"100"}'
|
|
# expect_json(ok = false, http = 400)
|
|
#
|
|
# vm = fetch_vm('testhost')
|
|
# expect(vm['lifetime']).to be_nil
|
|
# end
|
|
end
|
|
|
|
context '(auth configured)' do
|
|
before(:each) do
|
|
app.settings.set :config, auth: true
|
|
end
|
|
|
|
it 'allows VM lifetime to be modified with a token' do
|
|
create_vm('testhost', redis)
|
|
|
|
put "#{prefix}/vm/testhost", '{"lifetime":"1"}', {
|
|
'HTTP_X_AUTH_TOKEN' => 'abcdefghijklmnopqrstuvwxyz012345'
|
|
}
|
|
expect_json(ok = true, http = 200)
|
|
|
|
vm = fetch_vm('testhost')
|
|
expect(vm['lifetime'].to_i).to eq(1)
|
|
end
|
|
|
|
it 'does not allows VM lifetime to be modified without a token' do
|
|
create_vm('testhost', redis)
|
|
|
|
put "#{prefix}/vm/testhost", '{"lifetime":"1"}'
|
|
expect_json(ok = false, http = 401)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'DELETE /vm/:hostname' do
|
|
context '(auth not configured)' do
|
|
it 'does not delete a non-existant VM' do
|
|
delete "#{prefix}/vm/testhost"
|
|
expect_json(ok = false, http = 404)
|
|
end
|
|
|
|
it 'deletes an existing VM' do
|
|
create_running_vm('pool1', 'testhost', redis)
|
|
expect fetch_vm('testhost')
|
|
|
|
delete "#{prefix}/vm/testhost"
|
|
expect_json(ok = true, http = 200)
|
|
expect !fetch_vm('testhost')
|
|
end
|
|
end
|
|
|
|
context '(auth configured)' do
|
|
before(:each) do
|
|
app.settings.set :config, auth: true
|
|
end
|
|
|
|
context '(checked-out without token)' do
|
|
it 'deletes a VM without supplying a token' do
|
|
create_running_vm('pool1', 'testhost', redis)
|
|
expect fetch_vm('testhost')
|
|
|
|
delete "#{prefix}/vm/testhost"
|
|
expect_json(ok = true, http = 200)
|
|
expect !fetch_vm('testhost')
|
|
end
|
|
end
|
|
|
|
context '(checked-out with token)' do
|
|
it 'fails to delete a VM without supplying a token' do
|
|
create_running_vm('pool1', 'testhost', redis, 'abcdefghijklmnopqrstuvwxyz012345')
|
|
expect fetch_vm('testhost')
|
|
|
|
delete "#{prefix}/vm/testhost"
|
|
expect_json(ok = false, http = 401)
|
|
expect fetch_vm('testhost')
|
|
end
|
|
|
|
it 'deletes a VM when token is supplied' do
|
|
create_running_vm('pool1', 'testhost', redis, 'abcdefghijklmnopqrstuvwxyz012345')
|
|
expect fetch_vm('testhost')
|
|
|
|
delete "#{prefix}/vm/testhost", "", {
|
|
'HTTP_X_AUTH_TOKEN' => 'abcdefghijklmnopqrstuvwxyz012345'
|
|
}
|
|
expect_json(ok = true, http = 200)
|
|
|
|
expect !fetch_vm('testhost')
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'POST /vm/:hostname/snapshot' do
|
|
context '(auth not configured)' do
|
|
it 'creates a snapshot' do
|
|
create_vm('testhost', redis)
|
|
post "#{prefix}/vm/testhost/snapshot"
|
|
expect_json(ok = true, http = 202)
|
|
expect(JSON.parse(last_response.body)['testhost']['snapshot'].length).to be(32)
|
|
end
|
|
end
|
|
|
|
context '(auth configured)' do
|
|
before(:each) do
|
|
app.settings.set :config, auth: true
|
|
end
|
|
|
|
it 'returns a 401 if not authed' do
|
|
post "#{prefix}/vm/testhost/snapshot"
|
|
expect_json(ok = false, http = 401)
|
|
expect !has_vm_snapshot?('testhost', redis)
|
|
end
|
|
|
|
it 'creates a snapshot if authed' do
|
|
create_vm('testhost', redis)
|
|
snapshot_vm('testhost', 'testsnapshot', redis)
|
|
|
|
post "#{prefix}/vm/testhost/snapshot", "", {
|
|
'HTTP_X_AUTH_TOKEN' => 'abcdefghijklmnopqrstuvwxyz012345'
|
|
}
|
|
expect_json(ok = true, http = 202)
|
|
expect(JSON.parse(last_response.body)['testhost']['snapshot'].length).to be(32)
|
|
expect has_vm_snapshot?('testhost', redis)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'POST /vm/:hostname/snapshot/:snapshot' do
|
|
context '(auth not configured)' do
|
|
it 'reverts to a snapshot' do
|
|
create_vm('testhost', redis)
|
|
snapshot_vm('testhost', 'testsnapshot', redis)
|
|
|
|
post "#{prefix}/vm/testhost/snapshot/testsnapshot"
|
|
expect_json(ok = true, http = 202)
|
|
expect vm_reverted_to_snapshot?('testhost', redis, 'testsnapshot')
|
|
end
|
|
|
|
it 'fails if the specified snapshot does not exist' do
|
|
create_vm('testhost', redis)
|
|
|
|
post "#{prefix}/vm/testhost/snapshot/testsnapshot", "", {
|
|
'HTTP_X_AUTH_TOKEN' => 'abcdefghijklmnopqrstuvwxyz012345'
|
|
}
|
|
expect_json(ok = false, http = 404)
|
|
expect !vm_reverted_to_snapshot?('testhost', redis, 'testsnapshot')
|
|
end
|
|
end
|
|
|
|
context '(auth configured)' do
|
|
before(:each) do
|
|
app.settings.set :config, auth: true
|
|
end
|
|
|
|
it 'returns a 401 if not authed' do
|
|
create_vm('testhost', redis)
|
|
snapshot_vm('testhost', 'testsnapshot', redis)
|
|
|
|
post "#{prefix}/vm/testhost/snapshot/testsnapshot"
|
|
expect_json(ok = false, http = 401)
|
|
expect !vm_reverted_to_snapshot?('testhost', redis, 'testsnapshot')
|
|
end
|
|
|
|
it 'fails if authed and the specified snapshot does not exist' do
|
|
create_vm('testhost', redis)
|
|
|
|
post "#{prefix}/vm/testhost/snapshot/testsnapshot", "", {
|
|
'HTTP_X_AUTH_TOKEN' => 'abcdefghijklmnopqrstuvwxyz012345'
|
|
}
|
|
expect_json(ok = false, http = 404)
|
|
expect !vm_reverted_to_snapshot?('testhost', redis, 'testsnapshot')
|
|
end
|
|
|
|
it 'reverts to a snapshot if authed' do
|
|
create_vm('testhost', redis)
|
|
snapshot_vm('testhost', 'testsnapshot', redis)
|
|
|
|
post "#{prefix}/vm/testhost/snapshot/testsnapshot", "", {
|
|
'HTTP_X_AUTH_TOKEN' => 'abcdefghijklmnopqrstuvwxyz012345'
|
|
}
|
|
expect_json(ok = true, http = 202)
|
|
expect vm_reverted_to_snapshot?('testhost', redis, 'testsnapshot')
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|