Skip to content

Commit

Permalink
Rebasing fixed tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkergimenez committed Oct 31, 2019
1 parent de7d0fd commit 4bf7ee9
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 84 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ floaty get centos-7-x86_64=2 debian-7-x86_64 windows-10=3 --token mytokenstring

### 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

Expand Down Expand Up @@ -135,6 +135,7 @@ services:
url: 'https://abs.example.net/api/v2'
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:
Expand Down
1 change: 1 addition & 0 deletions lib/vmfloaty.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def run
c.option '--url STRING', String, 'URL of pooler service'
c.action do |args, options|
verbose = options.verbose || config['verbose']

service = Service.new(options, config)
filter = args[0]

Expand Down
126 changes: 68 additions & 58 deletions lib/vmfloaty/abs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def self.list(verbose, url, os_filter = nil)
os_list = []

response = conn.get 'status/platforms/vmpooler'

response_body = JSON.parse(response.body)
os_list << "*** VMPOOLER Pools ***"
os_list = os_list + JSON.parse(response_body["vmpooler_platforms"])
Expand All @@ -31,89 +32,98 @@ def self.list(verbose, url, os_filter = nil)

os_list.delete 'ok'

puts os_list

os_filter ? os_list.select { |i| i[/#{os_filter}/] } : os_list
end

# List active VMs from ABS
def self.list_active(verbose, url, token)
status = Auth.token_status(verbose, url, token)
status['reserved_hosts'] || []
end
# Retrieve an OS from ABS.
def self.retrieve(verbose, os_types, token, url, user)
#
# Contents of post must be:j
#
# {
# "resources": {
# "centos-7-i386": 1,
# "ubuntu-1404-x86_64": 2
# },
# "job": {
# "id": "12345",
# "tags": {
# "user": "jenkins",
# "jenkins_build_url": "https://jenkins/job/platform_puppet_intn-van-sys_master"
# }
# }
# }

def self.retrieve(verbose, os_type, token, url)
conn = Http.get_conn(verbose, url)
conn.headers['X-AUTH-TOKEN'] = token if token

os_string = os_type.map { |os, num| Array(os) * num }.flatten.join('+')
raise MissingParamError, 'No operating systems provided to obtain.' if os_string.empty?

response = conn.post "host/#{os_string}"

res_body = JSON.parse(response.body)
saved_job_id = Time.now.to_i

if res_body['ok']
res_body
elsif response.status == 401
raise AuthError, "HTTP #{response.status}: The token provided could not authenticate to the pooler.\n#{res_body}"
else
raise "HTTP #{response.status}: Failed to obtain VMs from the pooler at #{url}/host/#{os_string}. #{res_body}"
end
end
reqObj = {
resources: os_types,
job: {
id: saved_job_id,
tags: {
user: user,
url_string: "floaty://#{user}/#{saved_job_id}"
}
}
}

def self.modify(verbose, url, hostname, token, modify_hash)
raise TokenError, 'Token provided was nil; Request cannot be made to modify VM' if token.nil?
# 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."
response = conn.post "api/v2/request", reqObj.to_json

modify_hash.each do |key, _value|
raise ModifyError, "Configured service type does not support modification of #{key}" unless %i[reason reserved_for_reason].include? key
end
i = 0
retries = 360

if modify_hash[:reason]
# "reason" is easier to type than "reserved_for_reason", but nspooler needs the latter
modify_hash[:reserved_for_reason] = modify_hash.delete :reason
if response.status == 401
raise AuthError, "HTTP #{response.status}: The token provided could not authenticate to the pooler.\n#{res_body}"
end

conn = Http.get_conn(verbose, url)
conn.headers['X-AUTH-TOKEN'] = token
(1..retries).each do |i|
queue_place, res_body = check_queue(conn, saved_job_id, reqObj)
if res_body
return translated(res_body)
end

response = conn.put do |req|
req.url "host/#{hostname}"
req.body = modify_hash.to_json
puts "Waiting 10 seconds to check if ABS request has been filled. Queue Position: #{queue_place}... (x#{i})"
sleep(10)
end

response.body.empty? ? {} : JSON.parse(response.body)
return nil
end

def self.disk(_verbose, _url, _hostname, _token, _disk)
raise ModifyError, 'Configured service type does not support modification of disk space'
end

def self.snapshot(_verbose, _url, _hostname, _token)
raise ModifyError, 'Configured service type does not support snapshots'
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 = Hash.new

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

def self.revert(_verbose, _url, _hostname, _token, _snapshot_sha)
raise ModifyError, 'Configured service type does not support snapshots'
return vmpooler_formatted_body
end

def self.delete(verbose, url, hosts, token)
raise TokenError, 'Token provided was nil; Request cannot be made to delete VM' if token.nil?
def self.check_queue conn, job_id, reqObj
queue_info_response = conn.get "/status/queue/info/#{job_id}"
queue_info = JSON.parse(queue_info_response.body)

conn = Http.get_conn(verbose, url)
response = conn.post "api/v2/request", reqObj.to_json

conn.headers['X-AUTH-TOKEN'] = token if token

response_body = {}

hosts = hosts.split(',') unless hosts.is_a? Array
hosts.each do |host|
response = conn.delete "host/#{host}"
if response.body.length > 0
res_body = JSON.parse(response.body)
response_body[host] = res_body
return queue_info["queue_place"], res_body
end

response_body
return queue_info["queue_place"], nil
end

def self.status(verbose, url)
Expand Down
2 changes: 1 addition & 1 deletion lib/vmfloaty/nonstandard_pooler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def self.list_active(verbose, url, token)
status['reserved_hosts'] || []
end

def self.retrieve(verbose, os_type, token, url)
def self.retrieve(verbose, os_type, token, url, user)
conn = Http.get_conn(verbose, url)
conn.headers['X-AUTH-TOKEN'] = token if token

Expand Down
6 changes: 3 additions & 3 deletions lib/vmfloaty/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def type

def user
unless @config['user']
puts 'Enter your pooler service username:'
puts "Enter your #{@config["url"]} service username:"
@config['user'] = STDIN.gets.chomp
end
@config['user']
Expand All @@ -58,7 +58,7 @@ def get_new_token(verbose)

def delete_token(verbose, token_value = @config['token'])
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)
end

Expand All @@ -78,7 +78,7 @@ def list_active(verbose)
def retrieve(verbose, os_types, use_token = true)
puts 'Requesting a vm without a token...' unless use_token
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
end

def ssh(verbose, host_os, use_token = true)
Expand Down
2 changes: 2 additions & 0 deletions lib/vmfloaty/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ def self.standardize_hostnames(response_body)
# }
# }

# 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')

# vmpooler reports the domain separately from the hostname
Expand Down
22 changes: 9 additions & 13 deletions spec/vmfloaty/abs/auth_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

describe Pooler do
before :each do
@abs_url = 'https://abs.example.com'
@abs_url = 'https://abs.example.com/api/v2'
end

describe '#get_token' do
Expand All @@ -14,18 +14,16 @@
@token = 'utpg2i2xswor6h8ttjhu3d47z53yy47y'
end

it 'returns a token from vmpooler' do
stub_request(:post, 'https://first.last:[email protected]/api/v2/token')
.with(:headers => { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Length' => '0', 'User-Agent' => 'Faraday v0.9.2' })
it 'returns a token from abs' do
stub_request(:post, "https://first.last:[email protected]/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:[email protected]/api/v2/token')
.with(:headers => { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Length' => '0', 'User-Agent' => 'Faraday v0.9.2' })
stub_request(:post, "https://first.last:[email protected]/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)
Expand All @@ -39,16 +37,14 @@
end

it 'deletes the specified token' do
stub_request(:delete, 'https://first.last:[email protected]/api/v2/token/utpg2i2xswor6h8ttjhu3d47z53yy47y')
.with(:headers => { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent' => 'Faraday v0.9.2' })
.to_return(:status => 200, :body => @delete_token_response, :headers => {})
stub_request(:delete, "https://first.last:[email protected]/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:[email protected]/api/v2/token/utpg2i2xswor6h8ttjhu3d47z53yy47y')
.with(:headers => { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent' => 'Faraday v0.9.2' })
stub_request(:delete, "https://first.last:[email protected]/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)
Expand All @@ -67,15 +63,15 @@

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', 'User-Agent' => 'Faraday v0.9.2' })
.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', 'User-Agent' => 'Faraday v0.9.2' })
.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)
Expand Down
39 changes: 39 additions & 0 deletions spec/vmfloaty/abs_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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" => Hash.new,
"ubuntu-7.2-x86_64" => Hash.new
}

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
end
end
6 changes: 3 additions & 3 deletions spec/vmfloaty/nonstandard_pooler_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
.to_return(:status => 401, :body => '{"ok":false,"reason": "token: token-value does not exist"}', :headers => {})

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

it 'retrieves a single vm with a token' do
Expand All @@ -134,7 +134,7 @@
.to_return(:status => 200, :body => @retrieve_response_body_single, :headers => {})

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['ok']).to equal true
expect(vm_req['solaris-11-sparc']['hostname']).to eq 'sol11-4.delivery.puppetlabs.net'
Expand All @@ -146,7 +146,7 @@
.to_return(:status => 200, :body => @retrieve_response_body_many, :headers => {})

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['ok']).to equal true
expect(vm_req['solaris-10-sparc']['hostname']).to be_an_instance_of Array
Expand Down
Loading

0 comments on commit 4bf7ee9

Please sign in to comment.