Merge pull request #53 from mikkergimenez/add_abs_vm_get

Add abs vm get
This commit is contained in:
Brandon High 2019-12-04 16:43:26 -08:00 committed by GitHub
commit 6954321c87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 489 additions and 27 deletions

View file

@ -14,10 +14,12 @@ Style/TrailingCommaInArrayLiteral:
Style/TrailingCommaInArguments: Style/TrailingCommaInArguments:
EnforcedStyleForMultiline: comma EnforcedStyleForMultiline: comma
Layout/AlignHash: Layout/HashAlignment:
EnforcedHashRocketStyle: table EnforcedHashRocketStyle: table
Layout/IndentFirstHashElement: Layout/FirstHashElementIndentation:
EnforcedStyle: consistent EnforcedStyle: consistent
Metrics/ParameterLists:
Enabled: False
Style/StderrPuts: Style/StderrPuts:
Enabled: false Enabled: false

View file

@ -66,7 +66,7 @@ floaty get centos-7-x86_64=2 debian-7-x86_64 windows-10=3 --token mytokenstring
### vmfloaty dotfile ### vmfloaty dotfile
If you do not wish to continuely specify various config options with the cli, you can have a dotfile in your home directory for some defaults. For example: If you do not wish to continually specify various config options with the cli, you can have a dotfile in your home directory for some defaults. For example:
#### Basic configuration #### Basic configuration
@ -131,6 +131,11 @@ services:
url: 'https://nspooler.example.net/api/v1' url: 'https://nspooler.example.net/api/v1'
token: 'nspooler-tokenstring' token: 'nspooler-tokenstring'
type: 'nonstandard' # <-- 'type' is necessary for any non-vmpooler service type: 'nonstandard' # <-- 'type' is necessary for any non-vmpooler service
abs:
url: 'https://abs.example.net/'
token: 'abs-tokenstring'
type: 'abs' # <-- 'type' is necessary for any non-vmpooler service
``` ```
With this configuration, you could list available OS types from nspooler like this: With this configuration, you could list available OS types from nspooler like this:

View file

@ -17,7 +17,7 @@ require 'vmfloaty/ssh'
class Vmfloaty class Vmfloaty
include Commander::Methods include Commander::Methods
def run def run # rubocop:disable Metrics/AbcSize
program :version, Vmfloaty::VERSION program :version, Vmfloaty::VERSION
program :description, 'A CLI helper tool for Puppet Labs VM poolers to help you stay afloat' program :description, 'A CLI helper tool for Puppet Labs VM poolers to help you stay afloat'
@ -33,6 +33,7 @@ class Vmfloaty
c.option '--user STRING', String, 'User to authenticate with' c.option '--user STRING', String, 'User to authenticate with'
c.option '--url STRING', String, 'URL of pooler service' c.option '--url STRING', String, 'URL of pooler service'
c.option '--token STRING', String, 'Token for pooler service' c.option '--token STRING', String, 'Token for pooler service'
c.option '--priority STRING', 'Priority for supported backends(ABS) (High(1), Medium(2), Low(3))'
c.option '--notoken', 'Makes a request without a token' c.option '--notoken', 'Makes a request without a token'
c.option '--force', 'Forces vmfloaty to get requested vms' c.option '--force', 'Forces vmfloaty to get requested vms'
c.option '--json', 'Prints retrieved vms in JSON format' c.option '--json', 'Prints retrieved vms in JSON format'
@ -84,6 +85,7 @@ class Vmfloaty
c.option '--url STRING', String, 'URL of pooler service' c.option '--url STRING', String, 'URL of pooler service'
c.action do |args, options| c.action do |args, options|
verbose = options.verbose || config['verbose'] verbose = options.verbose || config['verbose']
service = Service.new(options, config) service = Service.new(options, config)
filter = args[0] filter = args[0]

285
lib/vmfloaty/abs.rb Normal file
View file

@ -0,0 +1,285 @@
# frozen_string_literal: true
require 'vmfloaty/errors'
require 'vmfloaty/http'
require 'faraday'
require 'json'
class ABS
# List active VMs in ABS
# This is what a job request looks like:
# {
# "state":"filled",
# "last_processed":"2019-10-31 20:59:33 +0000",
# "allocated_resources": [
# {
# "hostname":"h3oyntawjm7xdch.delivery.puppetlabs.net",
# "type":"centos-7.2-tmpfs-x86_64",
# "engine":"vmpooler"}
# ],
# "audit_log":{
# "2019-10-30 20:33:12 +0000":"Allocated h3oyntawjm7xdch.delivery.puppetlabs.net for job 1572467589"
# },
# "request":{
# "resources":{
# "centos-7.2-tmpfs-x86_64":1
# },
# "job": {
# "id":1572467589,
# "tags": {
# "user":"mikker",
# "url_string":"floaty://mikker/1572467589"
# },
# "user":"mikker",
# "time-received":1572467589
# }
# }
# }
#
@active_hostnames = {}
def self.list_active(verbose, url, _token, user)
all_jobs = []
@active_hostnames = {}
get_active_requests(verbose, url, user).each do |req_hash|
all_jobs.push(req_hash['request']['job']['id'])
@active_hostnames[req_hash['request']['job']['id']] = req_hash
end
all_jobs
end
def self.get_active_requests(verbose, url, user)
conn = Http.get_conn(verbose, url)
res = conn.get 'status/queue'
requests = JSON.parse(res.body)
ret_val = []
requests.each do |req|
req_hash = JSON.parse(req)
next unless user == req_hash['request']['job']['user']
ret_val.push(req_hash)
end
ret_val
end
def self.all_job_resources_accounted_for(allocated_resources, hosts)
allocated_host_list = allocated_resources.map { |ar| ar['hostname'] }
(allocated_host_list - hosts).empty?
end
def self.delete(verbose, url, hosts, token, user)
# In ABS terms, this is a "returned" host.
conn = Http.get_conn(verbose, url)
conn.headers['X-AUTH-TOKEN'] = token if token
puts "Trying to delete hosts #{hosts}" if verbose
requests = get_active_requests(verbose, url, user)
jobs_to_delete = []
ret_status = {}
hosts.each do |host|
ret_status[host] = {
'ok' => false,
}
end
requests.each do |req_hash|
next unless req_hash['state'] == 'allocated' || req_hash['state'] == 'filled'
req_hash['allocated_resources'].each do |vm_name, _i|
if hosts.include? vm_name['hostname']
if all_job_resources_accounted_for(req_hash['allocated_resources'], hosts)
ret_status[vm_name['hostname']] = {
'ok' => true,
}
jobs_to_delete.push(req_hash)
else
puts "When using ABS you must delete all vms that you requested at the same time: Can't delete #{req_hash['request']['job']['id']}: #{hosts} does not include all of #{req_hash['allocated_resources']}"
end
end
end
end
response_body = {}
jobs_to_delete.each do |job|
req_obj = {
'job_id' => job['request']['job']['id'],
'hosts' => job['allocated_resources'],
}
puts "Deleting #{req_obj}" if verbose
return_result = conn.post 'return', req_obj.to_json
req_obj['hosts'].each do |host|
response_body[host['hostname']] = { 'ok' => true } if return_result.body == 'OK'
end
end
response_body
end
# List available VMs in ABS
def self.list(verbose, url, os_filter = nil)
conn = Http.get_conn(verbose, url)
os_list = []
res = conn.get 'status/platforms/vmpooler'
res_body = JSON.parse(res.body)
os_list << '*** VMPOOLER Pools ***'
os_list += JSON.parse(res_body['vmpooler_platforms'])
res = conn.get 'status/platforms/nspooler'
res_body = JSON.parse(res.body)
os_list << ''
os_list << '*** NSPOOLER Pools ***'
os_list += JSON.parse(res_body['nspooler_platforms'])
res = conn.get 'status/platforms/aws'
res_body = JSON.parse(res.body)
os_list << ''
os_list << '*** AWS Pools ***'
os_list += JSON.parse(res_body['aws_platforms'])
os_list.delete 'ok'
os_filter ? os_list.select { |i| i[/#{os_filter}/] } : os_list
end
# Retrieve an OS from ABS.
def self.retrieve(verbose, os_types, token, url, user, options)
#
# Contents of post must be like:
#
# {
# "resources": {
# "centos-7-i386": 1,
# "ubuntu-1404-x86_64": 2
# },
# "job": {
# "id": "12345",
# "tags": {
# "user": "username",
# }
# }
# }
conn = Http.get_conn(verbose, url)
conn.headers['X-AUTH-TOKEN'] = token if token
saved_job_id = DateTime.now.strftime('%Q')
req_obj = {
:resources => os_types,
:job => {
:id => saved_job_id,
:tags => {
:user => user,
},
},
}
if options['priority']
req_obj[:priority] = if options['priority'] == 'high'
1
elsif options['priority'] == 'medium'
2
elsif options['priority'] == 'low'
3
else
options['priority'].to_i
end
end
puts "Posting to ABS #{req_obj.to_json}" if verbose
# os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+')
# raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty?
puts "Requesting VMs with job_id: #{saved_job_id}. Will retry for up to an hour."
res = conn.post 'request', req_obj.to_json
retries = 360
raise AuthError, "HTTP #{res.status}: The token provided could not authenticate to the pooler.\n#{res_body}" if res.status == 401
(1..retries).each do |i|
queue_place, res_body = check_queue(conn, saved_job_id, req_obj)
return translated(res_body) if res_body
sleep_seconds = 10 if i >= 10
sleep_seconds = i if i < 10
puts "Waiting #{sleep_seconds} seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})"
sleep(sleep_seconds)
end
nil
end
#
# We should fix the ABS API to be more like the vmpooler or nspooler api, but for now
#
def self.translated(res_body)
vmpooler_formatted_body = {}
res_body.each do |host|
if vmpooler_formatted_body[host['type']] && vmpooler_formatted_body[host['type']]['hostname'].class == Array
vmpooler_formatted_body[host['type']]['hostname'] << host['hostname']
else
vmpooler_formatted_body[host['type']] = { 'hostname' => [host['hostname']] }
end
end
vmpooler_formatted_body['ok'] = true
vmpooler_formatted_body
end
def self.check_queue(conn, job_id, req_obj)
queue_info_res = conn.get "status/queue/info/#{job_id}"
queue_info = JSON.parse(queue_info_res.body)
res = conn.post 'request', req_obj.to_json
unless res.body.empty?
res_body = JSON.parse(res.body)
return queue_info['queue_place'], res_body
end
[queue_info['queue_place'], nil]
end
def self.snapshot(_verbose, _url, _hostname, _token)
puts "Can't snapshot with ABS, use '--service vmpooler' (even for vms checked out with ABS)"
end
def self.status(verbose, url)
conn = Http.get_conn(verbose, url)
res = conn.get 'status'
res.body == 'OK'
end
def self.summary(verbose, url)
conn = Http.get_conn(verbose, url)
res = conn.get 'summary'
JSON.parse(res.body)
end
def self.query(verbose, url, hostname)
return @active_hostnames if @active_hostnames
puts "For vmpooler/snapshot information, use '--service vmpooler' (even for vms checked out with ABS)"
conn = Http.get_conn(verbose, url)
res = conn.get "host/#{hostname}"
JSON.parse(res.body)
end
end

View file

@ -17,12 +17,12 @@ class NonstandardPooler
os_filter ? os_list.select { |i| i[/#{os_filter}/] } : os_list os_filter ? os_list.select { |i| i[/#{os_filter}/] } : os_list
end end
def self.list_active(verbose, url, token) def self.list_active(verbose, url, token, _user)
status = Auth.token_status(verbose, url, token) status = Auth.token_status(verbose, url, token)
status['reserved_hosts'] || [] status['reserved_hosts'] || []
end end
def self.retrieve(verbose, os_type, token, url) def self.retrieve(verbose, os_type, token, url, _user, _options)
conn = Http.get_conn(verbose, url) conn = Http.get_conn(verbose, url)
conn.headers['X-AUTH-TOKEN'] = token if token conn.headers['X-AUTH-TOKEN'] = token if token

View file

@ -21,14 +21,14 @@ class Pooler
hosts hosts
end end
def self.list_active(verbose, url, token) def self.list_active(verbose, url, token, _user)
status = Auth.token_status(verbose, url, token) status = Auth.token_status(verbose, url, token)
vms = [] vms = []
vms = status[token]['vms']['running'] if status[token] && status[token]['vms'] vms = status[token]['vms']['running'] if status[token] && status[token]['vms']
vms vms
end end
def self.retrieve(verbose, os_type, token, url) def self.retrieve(verbose, os_type, token, url, _user, _options)
# NOTE: # NOTE:
# Developers can use `Utils.generate_os_hash` to # Developers can use `Utils.generate_os_hash` to
# generate the os_type param. # generate the os_type param.

View file

@ -36,7 +36,7 @@ class Service
def user def user
unless @config['user'] unless @config['user']
puts 'Enter your pooler service username:' puts "Enter your #{@config['url']} service username:"
@config['user'] = STDIN.gets.chomp @config['user'] = STDIN.gets.chomp
end end
@config['user'] @config['user']
@ -52,13 +52,13 @@ class Service
def get_new_token(verbose) def get_new_token(verbose)
username = user username = user
pass = Commander::UI.password 'Enter your pooler service password:', '*' pass = Commander::UI.password "Enter your #{@config['url']} service password:", '*'
Auth.get_token(verbose, url, username, pass) Auth.get_token(verbose, url, username, pass)
end end
def delete_token(verbose, token_value = @config['token']) def delete_token(verbose, token_value = @config['token'])
username = user username = user
pass = Commander::UI.password 'Enter your pooler service password:', '*' pass = Commander::UI.password "Enter your #{@config['url']} service password:", '*'
Auth.delete_token(verbose, url, username, pass, token_value) Auth.delete_token(verbose, url, username, pass, token_value)
end end
@ -72,13 +72,13 @@ class Service
end end
def list_active(verbose) def list_active(verbose)
@service_object.list_active verbose, url, token @service_object.list_active verbose, url, token, user
end end
def retrieve(verbose, os_types, use_token = true) def retrieve(verbose, os_types, use_token = true)
puts 'Requesting a vm without a token...' unless use_token puts 'Requesting a vm without a token...' unless use_token
token_value = use_token ? token : nil token_value = use_token ? token : nil
@service_object.retrieve verbose, os_types, token_value, url @service_object.retrieve verbose, os_types, token_value, url, user, @config
end end
def ssh(verbose, host_os, use_token = true) def ssh(verbose, host_os, use_token = true)
@ -112,7 +112,7 @@ class Service
end end
def delete(verbose, hosts) def delete(verbose, hosts)
@service_object.delete verbose, url, hosts, token @service_object.delete verbose, url, hosts, token, user
end end
def status(verbose) def status(verbose)

View file

@ -1,7 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'vmfloaty/pooler' require 'vmfloaty/abs'
require 'vmfloaty/nonstandard_pooler' require 'vmfloaty/nonstandard_pooler'
require 'vmfloaty/pooler'
class Utils class Utils
# TODO: Takes the json response body from an HTTP GET # TODO: Takes the json response body from an HTTP GET
@ -30,6 +31,13 @@ class Utils
# } # }
# } # }
# abs pooler response body example when `floaty get` arguments are :
# {
# "hostname"=>"thin-soutane.delivery.puppetlabs.net",
# "type"=>"centos-7.2-tmpfs-x86_64",
# "engine"=>"vmpooler"
# }
raise ArgumentError, "Bad GET response passed to format_hosts: #{response_body.to_json}" unless response_body.delete('ok') raise ArgumentError, "Bad GET response passed to format_hosts: #{response_body.to_json}" unless response_body.delete('ok')
# vmpooler reports the domain separately from the hostname # vmpooler reports the domain separately from the hostname
@ -77,6 +85,13 @@ class Utils
host_data = response[hostname] host_data = response[hostname]
case service.type case service.type
when 'ABS'
# For ABS, 'hostname' variable is the jobID
if host_data['state'] == 'allocated' || host_data['state'] == 'filled'
host_data['allocated_resources'].each do |vm_name, _i|
puts "- [JobID:#{host_data['request']['job']['id']}] #{vm_name['hostname']} (#{vm_name['type']}) <#{host_data['state']}>"
end
end
when 'Pooler' when 'Pooler'
tag_pairs = [] tag_pairs = []
tag_pairs = host_data['tags'].map { |key, value| "#{key}: #{value}" } unless host_data['tags'].nil? tag_pairs = host_data['tags'].map { |key, value| "#{key}: #{value}" } unless host_data['tags'].nil?
@ -140,6 +155,9 @@ class Utils
puts "#{name.ljust(width)} #{e.red}" puts "#{name.ljust(width)} #{e.red}"
end end
end end
when 'ABS'
puts 'ABS Not OK'.red unless status_response
puts 'ABS is OK'.green if status_response
else else
raise "Invalid service type #{service.type}" raise "Invalid service type #{service.type}"
end end
@ -155,8 +173,11 @@ class Utils
def self.get_service_object(type = '') def self.get_service_object(type = '')
nspooler_strings = %w[ns nspooler nonstandard nonstandard_pooler] nspooler_strings = %w[ns nspooler nonstandard nonstandard_pooler]
abs_strings = %w[abs alwaysbescheduling always_be_scheduling]
if nspooler_strings.include? type.downcase if nspooler_strings.include? type.downcase
NonstandardPooler NonstandardPooler
elsif abs_strings.include? type.downcase
ABS
else else
Pooler Pooler
end end
@ -187,6 +208,7 @@ class Utils
end end
# Prioritize an explicitly specified url, user, or token if the user provided one # Prioritize an explicitly specified url, user, or token if the user provided one
service_config['priority'] = options.priority unless options.priority.nil?
service_config['url'] = options.url unless options.url.nil? service_config['url'] = options.url unless options.url.nil?
service_config['token'] = options.token unless options.token.nil? service_config['token'] = options.token unless options.token.nil?
service_config['user'] = options.user unless options.user.nil? service_config['user'] = options.user unless options.user.nil?

View file

@ -0,0 +1,84 @@
# frozen_string_literal: true
require 'spec_helper'
require_relative '../../../lib/vmfloaty/auth'
describe Pooler do
before :each do
@abs_url = 'https://abs.example.com/api/v2'
end
describe '#get_token' do
before :each do
@get_token_response = '{"ok": true,"token":"utpg2i2xswor6h8ttjhu3d47z53yy47y"}'
@token = 'utpg2i2xswor6h8ttjhu3d47z53yy47y'
end
it 'returns a token from abs' do
stub_request(:post, 'https://first.last:password@abs.example.com/api/v2/token')
.to_return(:status => 200, :body => @get_token_response, :headers => {})
token = Auth.get_token(false, @abs_url, 'first.last', 'password')
expect(token).to eq @token
end
it 'raises a token error if something goes wrong' do
stub_request(:post, 'https://first.last:password@abs.example.com/api/v2/token')
.to_return(:status => 500, :body => '{"ok":false}', :headers => {})
expect { Auth.get_token(false, @abs_url, 'first.last', 'password') }.to raise_error(TokenError)
end
end
describe '#delete_token' do
before :each do
@delete_token_response = '{"ok":true}'
@token = 'utpg2i2xswor6h8ttjhu3d47z53yy47y'
end
it 'deletes the specified token' do
stub_request(:delete, 'https://first.last:password@abs.example.com/api/v2/token/utpg2i2xswor6h8ttjhu3d47z53yy47y')
.to_return(:status => 200, :body => @delete_token_response, :headers => {})
expect(Auth.delete_token(false, @abs_url, 'first.last', 'password', @token)).to eq JSON.parse(@delete_token_response)
end
it 'raises a token error if something goes wrong' do
stub_request(:delete, 'https://first.last:password@abs.example.com/api/v2/token/utpg2i2xswor6h8ttjhu3d47z53yy47y')
.to_return(:status => 500, :body => '{"ok":false}', :headers => {})
expect { Auth.delete_token(false, @abs_url, 'first.last', 'password', @token) }.to raise_error(TokenError)
end
it 'raises a token error if no token provided' do
expect { Auth.delete_token(false, @abs_url, 'first.last', 'password', nil) }.to raise_error(TokenError)
end
end
describe '#token_status' do
before :each do
@token_status_response = '{"ok":true,"utpg2i2xswor6h8ttjhu3d47z53yy47y":{"created":"2015-04-28 19:17:47 -0700"}}'
@token = 'utpg2i2xswor6h8ttjhu3d47z53yy47y'
end
it 'checks the status of a token' do
stub_request(:get, "#{@abs_url}/token/utpg2i2xswor6h8ttjhu3d47z53yy47y")
.with(:headers => { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3' })
.to_return(:status => 200, :body => @token_status_response, :headers => {})
expect(Auth.token_status(false, @abs_url, @token)).to eq JSON.parse(@token_status_response)
end
it 'raises a token error if something goes wrong' do
stub_request(:get, "#{@abs_url}/token/utpg2i2xswor6h8ttjhu3d47z53yy47y")
.with(:headers => { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3' })
.to_return(:status => 500, :body => '{"ok":false}', :headers => {})
expect { Auth.token_status(false, @abs_url, @token) }.to raise_error(TokenError)
end
it 'raises a token error if no token provided' do
expect { Auth.token_status(false, @abs_url, nil) }.to raise_error(TokenError)
end
end
end

62
spec/vmfloaty/abs_spec.rb Normal file
View file

@ -0,0 +1,62 @@
# frozen_string_literal: true
require 'spec_helper'
require 'vmfloaty/utils'
require 'vmfloaty/errors'
require 'vmfloaty/abs'
describe ABS do
before :each do
end
describe '#format' do
it 'returns an hash formatted like a vmpooler return' do
abs_formatted_response = [
{ 'hostname' => 'aaaaaaaaaaaaaaa.delivery.puppetlabs.net', 'type' => 'centos-7.2-x86_64', 'engine' => 'vmpooler' },
{ 'hostname' => 'aaaaaaaaaaaaaab.delivery.puppetlabs.net', 'type' => 'centos-7.2-x86_64', 'engine' => 'vmpooler' },
{ 'hostname' => 'aaaaaaaaaaaaaac.delivery.puppetlabs.net', 'type' => 'ubuntu-7.2-x86_64', 'engine' => 'vmpooler' },
]
vmpooler_formatted_response = ABS.translated(abs_formatted_response)
vmpooler_formatted_compare = {
'centos-7.2-x86_64' => {},
'ubuntu-7.2-x86_64' => {},
}
vmpooler_formatted_compare['centos-7.2-x86_64']['hostname'] = ['aaaaaaaaaaaaaaa.delivery.puppetlabs.net', 'aaaaaaaaaaaaaab.delivery.puppetlabs.net']
vmpooler_formatted_compare['ubuntu-7.2-x86_64']['hostname'] = ['aaaaaaaaaaaaaac.delivery.puppetlabs.net']
vmpooler_formatted_compare['ok'] = true
expect(vmpooler_formatted_response).to eq(vmpooler_formatted_compare)
vmpooler_formatted_response.delete('ok')
vmpooler_formatted_compare.delete('ok')
expect(vmpooler_formatted_response).to eq(vmpooler_formatted_compare)
end
it 'won\'t delete a job if not all vms are listed' do
hosts = ['host1']
allocated_resources = [
{
'hostname' => 'host1',
},
{
'hostname' => 'host2',
},
]
expect(ABS.all_job_resources_accounted_for(allocated_resources, hosts)).to eq(false)
hosts = ['host1', 'host2']
allocated_resources = [
{
'hostname' => 'host1',
},
{
'hostname' => 'host2',
},
]
expect(ABS.all_job_resources_accounted_for(allocated_resources, hosts)).to eq(true)
end
end
end

View file

@ -88,7 +88,7 @@ describe NonstandardPooler do
.with(false, @nspooler_url, 'token-value') .with(false, @nspooler_url, 'token-value')
.and_return(JSON.parse(@token_status_body_active)) .and_return(JSON.parse(@token_status_body_active))
list = NonstandardPooler.list_active(false, @nspooler_url, 'token-value') list = NonstandardPooler.list_active(false, @nspooler_url, 'token-value', 'user')
expect(list).to eql ['sol10-9', 'sol10-11'] expect(list).to eql ['sol10-9', 'sol10-11']
end end
end end
@ -125,7 +125,7 @@ describe NonstandardPooler do
.to_return(:status => 401, :body => '{"ok":false,"reason": "token: token-value does not exist"}', :headers => {}) .to_return(:status => 401, :body => '{"ok":false,"reason": "token: token-value does not exist"}', :headers => {})
vm_hash = { 'solaris-11-sparc' => 1 } vm_hash = { 'solaris-11-sparc' => 1 }
expect { NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url) }.to raise_error(AuthError) expect { NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url, 'first.last', {}) }.to raise_error(AuthError)
end end
it 'retrieves a single vm with a token' do it 'retrieves a single vm with a token' do
@ -134,7 +134,7 @@ describe NonstandardPooler do
.to_return(:status => 200, :body => @retrieve_response_body_single, :headers => {}) .to_return(:status => 200, :body => @retrieve_response_body_single, :headers => {})
vm_hash = { 'solaris-11-sparc' => 1 } vm_hash = { 'solaris-11-sparc' => 1 }
vm_req = NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url) vm_req = NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url, 'first.last', {})
expect(vm_req).to be_an_instance_of Hash expect(vm_req).to be_an_instance_of Hash
expect(vm_req['ok']).to equal true expect(vm_req['ok']).to equal true
expect(vm_req['solaris-11-sparc']['hostname']).to eq 'sol11-4.delivery.puppetlabs.net' expect(vm_req['solaris-11-sparc']['hostname']).to eq 'sol11-4.delivery.puppetlabs.net'
@ -146,7 +146,7 @@ describe NonstandardPooler do
.to_return(:status => 200, :body => @retrieve_response_body_many, :headers => {}) .to_return(:status => 200, :body => @retrieve_response_body_many, :headers => {})
vm_hash = { 'aix-7.1-power' => 1, 'solaris-10-sparc' => 2 } vm_hash = { 'aix-7.1-power' => 1, 'solaris-10-sparc' => 2 }
vm_req = NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url) vm_req = NonstandardPooler.retrieve(false, vm_hash, 'token-value', @nspooler_url, 'first.last', {})
expect(vm_req).to be_an_instance_of Hash expect(vm_req).to be_an_instance_of Hash
expect(vm_req['ok']).to equal true expect(vm_req['ok']).to equal true
expect(vm_req['solaris-10-sparc']['hostname']).to be_an_instance_of Array expect(vm_req['solaris-10-sparc']['hostname']).to be_an_instance_of Array

View file

@ -53,7 +53,7 @@ describe Pooler do
vm_hash = {} vm_hash = {}
vm_hash['debian-7-i386'] = 1 vm_hash['debian-7-i386'] = 1
expect { Pooler.retrieve(false, vm_hash, 'mytokenfile', @vmpooler_url) }.to raise_error(AuthError) expect { Pooler.retrieve(false, vm_hash, 'mytokenfile', @vmpooler_url, 'user', {}) }.to raise_error(AuthError)
end end
it 'retrieves a single vm with a token' do it 'retrieves a single vm with a token' do
@ -63,7 +63,7 @@ describe Pooler do
vm_hash = {} vm_hash = {}
vm_hash['debian-7-i386'] = 1 vm_hash['debian-7-i386'] = 1
vm_req = Pooler.retrieve(false, vm_hash, 'mytokenfile', @vmpooler_url) vm_req = Pooler.retrieve(false, vm_hash, 'mytokenfile', @vmpooler_url, 'user', {})
expect(vm_req).to be_an_instance_of Hash expect(vm_req).to be_an_instance_of Hash
expect(vm_req['ok']).to equal true expect(vm_req['ok']).to equal true
expect(vm_req['debian-7-i386']['hostname']).to eq 'fq6qlpjlsskycq6' expect(vm_req['debian-7-i386']['hostname']).to eq 'fq6qlpjlsskycq6'
@ -77,7 +77,7 @@ describe Pooler do
vm_hash = {} vm_hash = {}
vm_hash['debian-7-i386'] = 2 vm_hash['debian-7-i386'] = 2
vm_hash['centos-7-x86_64'] = 1 vm_hash['centos-7-x86_64'] = 1
vm_req = Pooler.retrieve(false, vm_hash, 'mytokenfile', @vmpooler_url) vm_req = Pooler.retrieve(false, vm_hash, 'mytokenfile', @vmpooler_url, 'user', {})
expect(vm_req).to be_an_instance_of Hash expect(vm_req).to be_an_instance_of Hash
expect(vm_req['ok']).to equal true expect(vm_req['ok']).to equal true
expect(vm_req['debian-7-i386']['hostname']).to be_an_instance_of Array expect(vm_req['debian-7-i386']['hostname']).to be_an_instance_of Array

View file

@ -16,9 +16,9 @@ describe Service do
it 'prompts the user for their password and retrieves a token' do it 'prompts the user for their password and retrieves a token' do
config = { 'user' => 'first.last', 'url' => 'http://default.url' } config = { 'user' => 'first.last', 'url' => 'http://default.url' }
service = Service.new(MockOptions.new, config) service = Service.new(MockOptions.new, config)
allow(STDOUT).to receive(:puts).with('Enter your pooler service password:') allow(STDOUT).to receive(:puts).with('Enter your http://default.url service password:')
allow(Commander::UI).to(receive(:password) allow(Commander::UI).to(receive(:password)
.with('Enter your pooler service password:', '*') .with('Enter your http://default.url service password:', '*')
.and_return('hunter2')) .and_return('hunter2'))
allow(Auth).to(receive(:get_token) allow(Auth).to(receive(:get_token)
.with(nil, config['url'], config['user'], 'hunter2') .with(nil, config['url'], config['user'], 'hunter2')
@ -29,11 +29,11 @@ describe Service do
it 'prompts the user for their username and password if the username is unknown' do it 'prompts the user for their username and password if the username is unknown' do
config = { 'url' => 'http://default.url' } config = { 'url' => 'http://default.url' }
service = Service.new(MockOptions.new({}), config) service = Service.new(MockOptions.new({}), config)
allow(STDOUT).to receive(:puts).with 'Enter your pooler service username:' allow(STDOUT).to receive(:puts).with 'Enter your http://default.url service username:'
allow(STDOUT).to receive(:puts).with "\n" allow(STDOUT).to receive(:puts).with "\n"
allow(STDIN).to receive(:gets).and_return('first.last') allow(STDIN).to receive(:gets).and_return('first.last')
allow(Commander::UI).to(receive(:password) allow(Commander::UI).to(receive(:password)
.with('Enter your pooler service password:', '*') .with('Enter your http://default.url service password:', '*')
.and_return('hunter2')) .and_return('hunter2'))
allow(Auth).to(receive(:get_token) allow(Auth).to(receive(:get_token)
.with(nil, config['url'], 'first.last', 'hunter2') .with(nil, config['url'], 'first.last', 'hunter2')
@ -46,7 +46,7 @@ describe Service do
it 'deletes a token' do it 'deletes a token' do
service = Service.new(MockOptions.new, 'user' => 'first.last', 'url' => 'http://default.url') service = Service.new(MockOptions.new, 'user' => 'first.last', 'url' => 'http://default.url')
allow(Commander::UI).to(receive(:password) allow(Commander::UI).to(receive(:password)
.with('Enter your pooler service password:', '*') .with('Enter your http://default.url service password:', '*')
.and_return('hunter2')) .and_return('hunter2'))
allow(Auth).to(receive(:delete_token) allow(Auth).to(receive(:delete_token)
.with(nil, 'http://default.url', 'first.last', 'hunter2', 'token-value') .with(nil, 'http://default.url', 'first.last', 'hunter2', 'token-value')