mirror of
https://github.com/puppetlabs/vmpooler.git
synced 2026-01-26 01:58:41 -05:00
(POOLER-123) Implement a max TTL (#349)
* (POOLER-123) Implement a max TTL Before this change, we could checkout a vm and set the lifetime to a very high number which would esssentially keep the vm running forever. Now implementing a config setting max_lifetime_upper_limit which enforces a maximum lifetime in hours both for initial checkout and extending a running vm * (POOLER-123) Improve PUT vm endpoint error messaging Prior to this commit the PUT vm endpoint didn't give any useful information about why a user's request failed. This commit updates PUT to output a more helpful set of error messages in the `failure` key that gets returned in the JSON response. * (POOLER-123) Update max_lifetime_upper_limit key This commit switches the max_lifetime_upper_limit key from being a symbol to being a string, which is what the config hash seems to contain. * (maint) Add option to disable Redis persistence in docker-compose This commit is just a handy little command override to the redis container to prevent persistence.
This commit is contained in:
parent
114cb9f398
commit
ae10bd4e22
5 changed files with 73 additions and 7 deletions
|
|
@ -22,6 +22,8 @@ services:
|
||||||
- redislocal
|
- redislocal
|
||||||
redislocal:
|
redislocal:
|
||||||
image: redis
|
image: redis
|
||||||
|
# Uncomment this if you don't want the redis data to persist
|
||||||
|
#command: "redis-server --save '' --appendonly no"
|
||||||
ports:
|
ports:
|
||||||
- "6379:6379"
|
- "6379:6379"
|
||||||
networks:
|
networks:
|
||||||
|
|
|
||||||
|
|
@ -875,7 +875,7 @@ module Vmpooler
|
||||||
status 404
|
status 404
|
||||||
result = { 'ok' => false }
|
result = { 'ok' => false }
|
||||||
|
|
||||||
failure = false
|
failure = []
|
||||||
|
|
||||||
params[:hostname] = hostname_shorten(params[:hostname], config['domain'])
|
params[:hostname] = hostname_shorten(params[:hostname], config['domain'])
|
||||||
|
|
||||||
|
|
@ -892,24 +892,42 @@ module Vmpooler
|
||||||
when 'lifetime'
|
when 'lifetime'
|
||||||
need_token! if Vmpooler::API.settings.config[:auth]
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
# in hours, defaults to one week
|
||||||
|
max_lifetime_upper_limit = config['max_lifetime_upper_limit']
|
||||||
|
if max_lifetime_upper_limit
|
||||||
|
max_lifetime_upper_limit = max_lifetime_upper_limit.to_i
|
||||||
|
if arg.to_i >= max_lifetime_upper_limit
|
||||||
|
failure.push("You provided a lifetime (#{arg}) that exceeds the configured maximum of #{max_lifetime_upper_limit}.")
|
||||||
|
else
|
||||||
|
# also make sure we do not extend past max_lifetime_upper_limit
|
||||||
|
rdata = backend.hgetall('vmpooler__vm__' + params[:hostname])
|
||||||
|
running = ((Time.now - Time.parse(rdata['checkout'])) / 60 / 60).round(2)
|
||||||
|
unless running + arg.to_i < max_lifetime_upper_limit
|
||||||
|
failure.push("You provided a lifetime (#{arg}) that will extend the current lifetime past the configured maximum of #{max_lifetime_upper_limit}.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# validate lifetime is within boundaries
|
||||||
unless arg.to_i > 0
|
unless arg.to_i > 0
|
||||||
failure = true
|
failure.push("You provided a lifetime (#{arg}) but you must provide a positive number.")
|
||||||
end
|
end
|
||||||
when 'tags'
|
when 'tags'
|
||||||
unless arg.is_a?(Hash)
|
unless arg.is_a?(Hash)
|
||||||
failure = true
|
failure.push("You provided tags (#{arg}) as something other than a hash.")
|
||||||
end
|
end
|
||||||
|
|
||||||
if config['allowed_tags']
|
if config['allowed_tags']
|
||||||
failure = true if not (arg.keys - config['allowed_tags']).empty?
|
failure.push("You provided unsuppored tags (#{arg}).") if not (arg.keys - config['allowed_tags']).empty?
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
failure = true
|
failure.push("Unknown argument #{arg}.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if failure
|
if failure.size > 0
|
||||||
status 400
|
status 400
|
||||||
|
result['failure'] = failure
|
||||||
else
|
else
|
||||||
jdata.each do |param, arg|
|
jdata.each do |param, arg|
|
||||||
case param
|
case param
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,10 @@ def fetch_vm(vm)
|
||||||
redis.hgetall("vmpooler__vm__#{vm}")
|
redis.hgetall("vmpooler__vm__#{vm}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_vm_data(vm, key, value)
|
||||||
|
redis.hset("vmpooler__vm__#{vm}", key, value)
|
||||||
|
end
|
||||||
|
|
||||||
def snapshot_revert_vm(vm, snapshot = '12345678901234567890123456789012')
|
def snapshot_revert_vm(vm, snapshot = '12345678901234567890123456789012')
|
||||||
redis.sadd('vmpooler__tasks__snapshot-revert', "#{vm}:#{snapshot}")
|
redis.sadd('vmpooler__tasks__snapshot-revert', "#{vm}:#{snapshot}")
|
||||||
redis.hset("vmpooler__vm__#{vm}", "snapshot:#{snapshot}", "1")
|
redis.hset("vmpooler__vm__#{vm}", "snapshot:#{snapshot}", "1")
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,14 @@ describe Vmpooler::API::V1 do
|
||||||
config: {
|
config: {
|
||||||
'site_name' => 'test pooler',
|
'site_name' => 'test pooler',
|
||||||
'vm_lifetime_auth' => 2,
|
'vm_lifetime_auth' => 2,
|
||||||
|
|
||||||
},
|
},
|
||||||
pools: [
|
pools: [
|
||||||
{'name' => 'pool1', 'size' => 5},
|
{'name' => 'pool1', 'size' => 5},
|
||||||
{'name' => 'pool2', 'size' => 10}
|
{'name' => 'pool2', 'size' => 10}
|
||||||
],
|
],
|
||||||
alias: { 'poolone' => 'pool1' },
|
alias: { 'poolone' => 'pool1' },
|
||||||
|
auth: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,7 +36,6 @@ describe Vmpooler::API::V1 do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
app.settings.set :config, config
|
app.settings.set :config, config
|
||||||
app.settings.set :redis, redis
|
app.settings.set :redis, redis
|
||||||
app.settings.set :config, auth: false
|
|
||||||
create_token('abcdefghijklmnopqrstuvwxyz012345', 'jdoe', current_time)
|
create_token('abcdefghijklmnopqrstuvwxyz012345', 'jdoe', current_time)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -122,6 +123,41 @@ describe Vmpooler::API::V1 do
|
||||||
vm = fetch_vm('testhost')
|
vm = fetch_vm('testhost')
|
||||||
expect(vm['lifetime']).to be_nil
|
expect(vm['lifetime']).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does not enforce a lifetime' do
|
||||||
|
create_vm('testhost')
|
||||||
|
|
||||||
|
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 168' do
|
||||||
|
app.settings.set :config,
|
||||||
|
{ :config => { 'max_lifetime_upper_limit' => 168 } }
|
||||||
|
create_vm('testhost')
|
||||||
|
|
||||||
|
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')
|
||||||
|
|
||||||
|
set_vm_data('testhost', "checkout", (Time.now - (69*60*60)))
|
||||||
|
put "#{prefix}/vm/testhost", '{"lifetime":"100"}'
|
||||||
|
expect_json(ok = false, http = 400)
|
||||||
|
|
||||||
|
vm = fetch_vm('testhost')
|
||||||
|
expect(vm['lifetime']).to be_nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context '(auth configured)' do
|
context '(auth configured)' do
|
||||||
|
|
|
||||||
|
|
@ -498,6 +498,12 @@
|
||||||
# Expects a boolean value
|
# Expects a boolean value
|
||||||
# (optional; default: false)
|
# (optional; default: false)
|
||||||
#
|
#
|
||||||
|
# - max_lifetime_upper_limit
|
||||||
|
# Sets a lifetime upper limit (in hours) for how long the vm lifetime can be set via the API. Lifetime can be set and extended
|
||||||
|
# so this configuration is used to enforce an upper limit to both the initial lifetime request and/or the extended
|
||||||
|
# lifetime (by checking how long it has already been running).
|
||||||
|
# (optional; default: unlimited)
|
||||||
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
|
||||||
:config:
|
:config:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue