class Kitchen::Driver::VmpoolStores::VmpoolerStore

Attributes

lifetime[R]
tags[R]
token[R]
vmpooler_url[R]

Public Class Methods

new(opts = {}) click to toggle source

@param [Hash] opts @option opts [String] :host_url The hostname to use in http requests. @option opts [String] :user (nil) A username for authentication. Optional only if token is valid. @option opts [String] :password (nil) A password for authentication. Optional only if token is valid. @option opts [String] :token (nil) A preloaded token to use in requests. Optional only if

user and pass are valid.

@raise [InvalidUrl] if vmpooler url is invalid

# File lib/kitchen/driver/vmpool_stores/vmpooler_store.rb, line 19
def initialize(opts = {})
  host_url = opts.fetch('host_url')
  user = opts.fetch('user', nil)
  pass = opts.fetch('pass', nil)
  token = opts.fetch('token', nil)
  @tags = opts.fetch('tags', { purpose: 'vmpooler-default' })
  @lifetime = opts.fetch('lifetime', nil)
  @vmpooler_url = URI.join(host_url, '/api/v1/').to_s
  raise Kitchen::Driver::InvalidUrl.new("Bad url: #{vmpooler_url}") unless valid_url?(URI.join(vmpooler_url, 'vm'))
  @token = valid_token?(token) ? token : create_token(user, pass)
end

Public Instance Methods

cleanup(pool_member:, pool_name: nil, reuse_instances: false) { |pool_member, used_status| ... } click to toggle source

@param pool_member [String] the pool member to destroy

# File lib/kitchen/driver/vmpool_stores/vmpooler_store.rb, line 38
def cleanup(pool_member:, pool_name: nil, reuse_instances: false)
  used_status = 'destroyed'
  destroy_pool_member(pool_member)
  yield(pool_member, used_status) if block_given?
end
take_pool_member(pool_name) click to toggle source

@param pool_name [String] the pool to take from @return [String] a pool member from the pool

# File lib/kitchen/driver/vmpool_stores/vmpooler_store.rb, line 33
def take_pool_member(pool_name)
  fetch_pool_member(pool_name)
end

Private Instance Methods

create_token(user, pass) click to toggle source

@param user [String] @param pass [String] @return [String] a new token if the http response code is 200 @raise [InvalidCredentials] if the http response code is 401 @raise [TokenNotCreated] if the http response code is otherwise not 200

# File lib/kitchen/driver/vmpool_stores/vmpooler_store.rb, line 96
def create_token(user, pass)
  uri = URI.join(vmpooler_url, 'token')
  request = Net::HTTP::Post.new(uri)
  request.basic_auth(user, pass)

  req_options = {
      use_ssl: uri.scheme == 'https',
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end

  return JSON.parse(response.body)['token'] if response.code == '200'
  raise Kitchen::Driver::InvalidCredentials.new("Username or password are invalid") if response.code == '401'
  raise Kitchen::Driver::TokenNotCreated.new("Unable to create token, got response code: #{response.code}")
end
destroy_pool_member(pool_member) click to toggle source

@param pool_member [String] a VM instance to destroy @raise [PoolMemberNotFound] if the pool member was not found @raise [PoolMemberNotDestroyed] if the pool member was not destroyed

# File lib/kitchen/driver/vmpool_stores/vmpooler_store.rb, line 70
def destroy_pool_member(pool_member)
  uri = URI.join(vmpooler_url, 'vm/', pool_member)
  request = Net::HTTP::Delete.new(uri)
  request.add_field('X-AUTH-TOKEN', token)

  req_options = {
      use_ssl: uri.scheme == 'https',
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end

  case
  when response.code == '404'
    raise Kitchen::Driver::PoolMemberNotFound.new("Pool member #{pool_member} was not found")
  when response.code != '200'
    raise Kitchen::Driver::PoolMemberNotDestroyed.new("Error destroying pool member: code #{response.code}, message #{response.body}")
  end
end
fetch_pool_member(pool_name, number_of_vms = 1) click to toggle source

@return Array - array of hostnames @param pool_name [String] - the name of the pool to get hostnames from @param number_of_vms [Integer] - a postive number of vms to fetch

# File lib/kitchen/driver/vmpool_stores/vmpooler_store.rb, line 117
def fetch_pool_member(pool_name, number_of_vms = 1)
  uri = URI.join(vmpooler_url, 'vm')
  request = Net::HTTP::Post.new(uri)
  request.body = JSON.dump({ pool_name => number_of_vms.to_s })
  request.add_field('X-AUTH-TOKEN', token)

  req_options = {
      use_ssl: uri.scheme == 'https',
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end

  case response.code
  when '200'
    data = JSON.parse(response.body)
    data[pool_name]['hostname']
  when '503'
    msg = "Pool #{pool_name} does not have enough active pool members, please try later."
    raise Kitchen::Driver::PoolMemberUnavailable.new(msg)
  when '404'
    raise Kitchen::Driver::PoolNotFound.new("Pool #{pool_name} was not found")
  else
    raise Exception.new("Error: code #{response.code}, message #{response.body}")
  end
end
valid_token?(token) click to toggle source

@param token [String] the token to validate @return [true] if the token url is valid @return [false] if the token url is invalid

# File lib/kitchen/driver/vmpool_stores/vmpooler_store.rb, line 49
def valid_token?(token)
  if token and token.length > 5
    token_url = URI.join(vmpooler_url, 'token', token).to_s
    valid_url?(token_url)
  end
end
valid_url?(url) click to toggle source

@param url [String] a url to validate @return [true] if the http response code is 200 @return [false] if the http response code is not 200

# File lib/kitchen/driver/vmpool_stores/vmpooler_store.rb, line 59
def valid_url?(url)
  if url
    uri = URI(url)
    response = Net::HTTP.get_response(uri)
    response.code == '200'
  end
end