mirror of
https://github.com/puppetlabs/vmpooler.git
synced 2026-01-26 01:58:41 -05:00
Update hostname_shorten and callers
This commit is contained in:
parent
35dc7cb26f
commit
0119126cd1
3 changed files with 394 additions and 34 deletions
|
|
@ -181,8 +181,7 @@ module Vmpooler
|
||||||
/^\d{4}-\d{2}-\d{2}$/ === date_str
|
/^\d{4}-\d{2}-\d{2}$/ === date_str
|
||||||
end
|
end
|
||||||
|
|
||||||
# NOTE: domain is not needed here, so we should update the callers of this method
|
def hostname_shorten(hostname)
|
||||||
def hostname_shorten(hostname, domain=nil)
|
|
||||||
hostname[/[^.]+/]
|
hostname[/[^.]+/]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ module Vmpooler
|
||||||
status 404
|
status 404
|
||||||
result['ok'] = false
|
result['ok'] = false
|
||||||
|
|
||||||
params[:hostname] = hostname_shorten(params[:hostname], nil)
|
params[:hostname] = hostname_shorten(params[:hostname])
|
||||||
|
|
||||||
rdata = backend.hgetall("vmpooler__vm__#{params[:hostname]}")
|
rdata = backend.hgetall("vmpooler__vm__#{params[:hostname]}")
|
||||||
unless rdata.empty?
|
unless rdata.empty?
|
||||||
|
|
@ -467,32 +467,395 @@ module Vmpooler
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Endpoints that only use bits from the V1 api are called here
|
delete "#{api_prefix}/vm/:hostname/?" do
|
||||||
# Note that traces will be named based on the route used in the V1 api
|
content_type :json
|
||||||
# but the http.url trace attribute will still have the actual requested url in it
|
metrics.increment('http_requests_vm_total.delete.vm.hostname')
|
||||||
|
|
||||||
delete "#{api_prefix}/*" do
|
result = {}
|
||||||
versionless_path_info = request.path_info.delete_prefix("#{api_prefix}/")
|
|
||||||
request.path_info = "/api/v1/#{versionless_path_info}"
|
status 404
|
||||||
call env
|
result['ok'] = false
|
||||||
|
|
||||||
|
params[:hostname] = hostname_shorten(params[:hostname])
|
||||||
|
|
||||||
|
rdata = backend.hgetall("vmpooler__vm__#{params[:hostname]}")
|
||||||
|
unless rdata.empty?
|
||||||
|
need_token! if rdata['token:token']
|
||||||
|
|
||||||
|
if backend.srem("vmpooler__running__#{rdata['template']}", params[:hostname])
|
||||||
|
backend.sadd("vmpooler__completed__#{rdata['template']}", params[:hostname])
|
||||||
|
|
||||||
|
status 200
|
||||||
|
result['ok'] = true
|
||||||
|
metrics.increment('delete.success')
|
||||||
|
update_user_metrics('destroy', params[:hostname]) if Vmpooler::API.settings.config[:config]['usage_stats']
|
||||||
|
else
|
||||||
|
metrics.increment('delete.failed')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
get "#{api_prefix}/*" do
|
put "#{api_prefix}/vm/:hostname/?" do
|
||||||
versionless_path_info = request.path_info.delete_prefix("#{api_prefix}/")
|
content_type :json
|
||||||
request.path_info = "/api/v1/#{versionless_path_info}"
|
metrics.increment('http_requests_vm_total.put.vm.modify')
|
||||||
call env
|
|
||||||
|
status 404
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
failure = []
|
||||||
|
|
||||||
|
params[:hostname] = hostname_shorten(params[:hostname])
|
||||||
|
|
||||||
|
if backend.exists?("vmpooler__vm__#{params[:hostname]}")
|
||||||
|
begin
|
||||||
|
jdata = JSON.parse(request.body.read)
|
||||||
|
rescue StandardError => e
|
||||||
|
span = OpenTelemetry::Trace.current_span
|
||||||
|
span.record_exception(e)
|
||||||
|
span.status = OpenTelemetry::Trace::Status.error(e.to_s)
|
||||||
|
halt 400, JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Validate data payload
|
||||||
|
jdata.each do |param, arg|
|
||||||
|
case param
|
||||||
|
when 'lifetime'
|
||||||
|
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}.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# validate lifetime is within boundaries
|
||||||
|
unless arg.to_i > 0
|
||||||
|
failure.push("You provided a lifetime (#{arg}) but you must provide a positive number.")
|
||||||
|
end
|
||||||
|
|
||||||
|
when 'tags'
|
||||||
|
failure.push("You provided tags (#{arg}) as something other than a hash.") unless arg.is_a?(Hash)
|
||||||
|
failure.push("You provided unsuppored tags (#{arg}).") if config['allowed_tags'] && !(arg.keys - config['allowed_tags']).empty?
|
||||||
|
else
|
||||||
|
failure.push("Unknown argument #{arg}.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if !failure.empty?
|
||||||
|
status 400
|
||||||
|
result['failure'] = failure
|
||||||
|
else
|
||||||
|
jdata.each do |param, arg|
|
||||||
|
case param
|
||||||
|
when 'lifetime'
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
arg = arg.to_i
|
||||||
|
|
||||||
|
backend.hset("vmpooler__vm__#{params[:hostname]}", param, arg)
|
||||||
|
when 'tags'
|
||||||
|
filter_tags(arg)
|
||||||
|
export_tags(backend, params[:hostname], arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
status 200
|
||||||
|
result['ok'] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
post "#{api_prefix}/*" do
|
post "#{api_prefix}/vm/:hostname/disk/:size/?" do
|
||||||
versionless_path_info = request.path_info.delete_prefix("#{api_prefix}/")
|
content_type :json
|
||||||
request.path_info = "/api/v1/#{versionless_path_info}"
|
metrics.increment('http_requests_vm_total.post.vm.disksize')
|
||||||
call env
|
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
status 404
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
params[:hostname] = hostname_shorten(params[:hostname])
|
||||||
|
|
||||||
|
if ((params[:size].to_i > 0 )and (backend.exists?("vmpooler__vm__#{params[:hostname]}")))
|
||||||
|
result[params[:hostname]] = {}
|
||||||
|
result[params[:hostname]]['disk'] = "+#{params[:size]}gb"
|
||||||
|
|
||||||
|
backend.sadd('vmpooler__tasks__disk', "#{params[:hostname]}:#{params[:size]}")
|
||||||
|
|
||||||
|
status 202
|
||||||
|
result['ok'] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
put "#{api_prefix}/*" do
|
post "#{api_prefix}/vm/:hostname/snapshot/?" do
|
||||||
versionless_path_info = request.path_info.delete_prefix("#{api_prefix}/")
|
content_type :json
|
||||||
request.path_info = "/api/v1/#{versionless_path_info}"
|
metrics.increment('http_requests_vm_total.post.vm.snapshot')
|
||||||
call env
|
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
status 404
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
params[:hostname] = hostname_shorten(params[:hostname])
|
||||||
|
|
||||||
|
if backend.exists?("vmpooler__vm__#{params[:hostname]}")
|
||||||
|
result[params[:hostname]] = {}
|
||||||
|
|
||||||
|
o = [('a'..'z'), ('0'..'9')].map(&:to_a).flatten
|
||||||
|
result[params[:hostname]]['snapshot'] = o[rand(25)] + (0...31).map { o[rand(o.length)] }.join
|
||||||
|
|
||||||
|
backend.sadd('vmpooler__tasks__snapshot', "#{params[:hostname]}:#{result[params[:hostname]]['snapshot']}")
|
||||||
|
|
||||||
|
status 202
|
||||||
|
result['ok'] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
post "#{api_prefix}/vm/:hostname/snapshot/:snapshot/?" do
|
||||||
|
content_type :json
|
||||||
|
metrics.increment('http_requests_vm_total.post.vm.snapshot')
|
||||||
|
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
status 404
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
params[:hostname] = hostname_shorten(params[:hostname])
|
||||||
|
|
||||||
|
unless backend.hget("vmpooler__vm__#{params[:hostname]}", "snapshot:#{params[:snapshot]}").to_i.zero?
|
||||||
|
backend.sadd('vmpooler__tasks__snapshot-revert', "#{params[:hostname]}:#{params[:snapshot]}")
|
||||||
|
|
||||||
|
status 202
|
||||||
|
result['ok'] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
delete "#{api_prefix}/config/poolsize/:pool/?" do
|
||||||
|
content_type :json
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
if config['experimental_features']
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
if pool_exists?(params[:pool])
|
||||||
|
result = reset_pool_size(params[:pool])
|
||||||
|
else
|
||||||
|
metrics.increment('config.invalid.unknown')
|
||||||
|
status 404
|
||||||
|
end
|
||||||
|
else
|
||||||
|
status 405
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
post "#{api_prefix}/config/poolsize/?" do
|
||||||
|
content_type :json
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
if config['experimental_features']
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
payload = JSON.parse(request.body.read)
|
||||||
|
|
||||||
|
if payload
|
||||||
|
invalid = invalid_template_or_size(payload)
|
||||||
|
if invalid.empty?
|
||||||
|
result = update_pool_size(payload)
|
||||||
|
else
|
||||||
|
invalid.each do |bad_template|
|
||||||
|
metrics.increment("config.invalid.#{bad_template}")
|
||||||
|
end
|
||||||
|
result[:not_configured] = invalid
|
||||||
|
status 400
|
||||||
|
end
|
||||||
|
else
|
||||||
|
metrics.increment('config.invalid.unknown')
|
||||||
|
status 404
|
||||||
|
end
|
||||||
|
else
|
||||||
|
status 405
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
delete "#{api_prefix}/config/pooltemplate/:pool/?" do
|
||||||
|
content_type :json
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
if config['experimental_features']
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
if pool_exists?(params[:pool])
|
||||||
|
result = reset_pool_template(params[:pool])
|
||||||
|
else
|
||||||
|
metrics.increment('config.invalid.unknown')
|
||||||
|
status 404
|
||||||
|
end
|
||||||
|
else
|
||||||
|
status 405
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
post "#{api_prefix}/config/pooltemplate/?" do
|
||||||
|
content_type :json
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
if config['experimental_features']
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
payload = JSON.parse(request.body.read)
|
||||||
|
|
||||||
|
if payload
|
||||||
|
invalid = invalid_template_or_path(payload)
|
||||||
|
if invalid.empty?
|
||||||
|
result = update_pool_template(payload)
|
||||||
|
else
|
||||||
|
invalid.each do |bad_template|
|
||||||
|
metrics.increment("config.invalid.#{bad_template}")
|
||||||
|
end
|
||||||
|
result[:bad_templates] = invalid
|
||||||
|
status 400
|
||||||
|
end
|
||||||
|
else
|
||||||
|
metrics.increment('config.invalid.unknown')
|
||||||
|
status 404
|
||||||
|
end
|
||||||
|
else
|
||||||
|
status 405
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
post "#{api_prefix}/poolreset/?" do
|
||||||
|
content_type :json
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
if config['experimental_features']
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
begin
|
||||||
|
payload = JSON.parse(request.body.read)
|
||||||
|
if payload
|
||||||
|
invalid = invalid_templates(payload)
|
||||||
|
if invalid.empty?
|
||||||
|
result = reset_pool(payload)
|
||||||
|
else
|
||||||
|
invalid.each do |bad_pool|
|
||||||
|
metrics.increment("poolreset.invalid.#{bad_pool}")
|
||||||
|
end
|
||||||
|
result[:bad_pools] = invalid
|
||||||
|
status 400
|
||||||
|
end
|
||||||
|
else
|
||||||
|
metrics.increment('poolreset.invalid.unknown')
|
||||||
|
status 404
|
||||||
|
end
|
||||||
|
rescue JSON::ParserError
|
||||||
|
span = OpenTelemetry::Trace.current_span
|
||||||
|
span.record_exception(e)
|
||||||
|
span.status = OpenTelemetry::Trace::Status.error('JSON payload could not be parsed')
|
||||||
|
status 400
|
||||||
|
result = {
|
||||||
|
'ok' => false,
|
||||||
|
'message' => 'JSON payload could not be parsed'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
status 405
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
post "#{api_prefix}/config/clonetarget/?" do
|
||||||
|
content_type :json
|
||||||
|
result = { 'ok' => false }
|
||||||
|
|
||||||
|
if config['experimental_features']
|
||||||
|
need_token! if Vmpooler::API.settings.config[:auth]
|
||||||
|
|
||||||
|
payload = JSON.parse(request.body.read)
|
||||||
|
|
||||||
|
if payload
|
||||||
|
invalid = invalid_pool(payload)
|
||||||
|
if invalid.empty?
|
||||||
|
result = update_clone_target(payload)
|
||||||
|
else
|
||||||
|
invalid.each do |bad_template|
|
||||||
|
metrics.increment("config.invalid.#{bad_template}")
|
||||||
|
end
|
||||||
|
result[:bad_templates] = invalid
|
||||||
|
status 400
|
||||||
|
end
|
||||||
|
else
|
||||||
|
metrics.increment('config.invalid.unknown')
|
||||||
|
status 404
|
||||||
|
end
|
||||||
|
else
|
||||||
|
status 405
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
get "#{api_prefix}/config/?" do
|
||||||
|
content_type :json
|
||||||
|
result = { 'ok' => false }
|
||||||
|
status 404
|
||||||
|
|
||||||
|
if pools
|
||||||
|
sync_pool_sizes
|
||||||
|
sync_pool_templates
|
||||||
|
|
||||||
|
pool_configuration = []
|
||||||
|
pools.each do |pool|
|
||||||
|
pool['template_ready'] = template_ready?(pool, backend)
|
||||||
|
pool_configuration << pool
|
||||||
|
end
|
||||||
|
|
||||||
|
result = {
|
||||||
|
pool_configuration: pool_configuration,
|
||||||
|
status: {
|
||||||
|
ok: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status 200
|
||||||
|
end
|
||||||
|
JSON.pretty_generate(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
get "#{api_prefix}/full_config/?" do
|
||||||
|
content_type :json
|
||||||
|
|
||||||
|
result = {
|
||||||
|
full_config: full_config,
|
||||||
|
status: {
|
||||||
|
ok: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status 200
|
||||||
|
JSON.pretty_generate(result)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,12 @@ describe Vmpooler::API::Helpers do
|
||||||
|
|
||||||
describe '#hostname_shorten' do
|
describe '#hostname_shorten' do
|
||||||
[
|
[
|
||||||
['example.com', 'not-example.com', 'example'],
|
['example.com', 'example'],
|
||||||
['example.com', 'example.com', 'example'],
|
['sub.example.com', 'sub'],
|
||||||
['sub.example.com', 'example.com', 'sub'],
|
['adjective-noun.example.com', 'adjective-noun'],
|
||||||
['adjective-noun.example.com', 'example.com', 'adjective-noun'],
|
['abc123.example.com', 'abc123']
|
||||||
['abc123.example.com', 'example.com', 'abc123'],
|
].each do |hostname, expected|
|
||||||
['example.com', nil, 'example']
|
it { expect(subject.hostname_shorten(hostname)).to eq expected }
|
||||||
].each do |hostname, domain, expected|
|
|
||||||
it { expect(subject.hostname_shorten(hostname, domain)).to eq expected }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue