class Kitchen::Driver::Linode

Linode driver for Kitchen.

@author Brett Taylor <btaylor@linode.com>

Public Instance Methods

create(state) click to toggle source
# File lib/kitchen/driver/linode.rb, line 60
def create(state)
  # create and boot server
  config_server_name
  set_password
  
  if state[:linode_id]
    info "#{config[:server_name]} (#{state[:linode_id]}) already exists."
    return
  end
  
  info("Creating Linode - #{config[:server_name]}")
  
  server = create_server
  
  # assign the machine id for reference in other commands
  state[:linode_id] = server.id
  state[:hostname] = server.public_ip_address
  info("Linode <#{state[:linode_id]}> created.")
  info("Waiting for linode to boot...")
  server.wait_for { ready? }
  info("Linode <#{state[:linode_id]}, #{state[:hostname]}> ready.")
  setup_ssh(state) if bourne_shell?
rescue Fog::Errors::Error, Excon::Errors::Error => ex
  raise ActionFailed, ex.message
end
destroy(state) click to toggle source
# File lib/kitchen/driver/linode.rb, line 86
def destroy(state)
  return if state[:linode_id].nil?
  server = compute.servers.get(state[:linode_id])

  server.destroy

  info("Linode <#{state[:linode_id]}> destroyed.")
  state.delete(:linode_id)
  state.delete(:pub_ip)
end

Private Instance Methods

compute() click to toggle source
# File lib/kitchen/driver/linode.rb, line 99
def compute
  Fog::Compute.new(:provider => 'Linode', :linode_api_key => config[:api_key])
end
config_server_name() click to toggle source

Set the proper server name in the config

# File lib/kitchen/driver/linode.rb, line 222
def config_server_name
  if config[:server_name]
    config[:vm_hostname] = "#{config[:server_name]}"
    config[:server_name] = "kitchen-#{config[:server_name]}-#{instance.name}-#{Time.now.to_i.to_s}"
  else
    config[:vm_hostname] = "#{instance.name}"
    if ENV["JOB_NAME"]
      # use jenkins job name variable. "kitchen_root" turns into "workspace" which is uninformative.
      jobname = ENV["JOB_NAME"]
    elsif ENV["TRAVIS_REPO_SLUG"]
      jobname = ENV["TRAVIS_REPO_SLUG"]
    else
      jobname = File.basename(config[:kitchen_root])
    end
    config[:server_name] = "kitchen-#{jobname}-#{instance.name}-#{Time.now.to_i.to_s}".tr(" /", "_")
  end
  
  # cut to fit Linode 32 character maximum
  if config[:server_name].is_a?(String) && config[:server_name].size >= 32
    config[:server_name] = "#{config[:server_name][0..29]}#{rand(10..99)}"
  end
end
create_server() click to toggle source
# File lib/kitchen/driver/linode.rb, line 161
def create_server
  data_center = get_dc
  flavor = get_flavor
  image = get_image
  kernel = get_kernel
  
  # submit new linode request
  compute.servers.create(
    :data_center => data_center,
    :flavor => flavor, 
    :payment_terms => config[:payment_terms], 
    :name => config[:server_name],
    :image => image,
    :kernel => kernel,
    :username => config[:username],
    :password => config[:password]
  )
end
do_ssh_setup(state, config) click to toggle source
# File lib/kitchen/driver/linode.rb, line 186
def do_ssh_setup(state, config)
  info "Setting up SSH access for key <#{config[:public_key_path]}>"
  info "Connecting <#{config[:username]}@#{state[:hostname]}>..."
  ssh = Fog::SSH.new(state[:hostname],
                     config[:username],
                     :password => config[:password],
                     :timeout => config[:ssh_timeout])
  pub_key = open(config[:public_key_path]).read
  shortname = "#{config[:vm_hostname].split('.')[0]}"
  hostsfile = "127.0.0.1 #{config[:vm_hostname]} #{shortname} localhost\n::1 #{config[:vm_hostname]} #{shortname} localhost"
  @max_interval = 60
  @max_retries = 10
  @retries = 0
  begin
    ssh.run([
      %(echo "#{hostsfile}" > /etc/hosts),
      %(hostnamectl set-hostname #{config[:vm_hostname]}),
      %(mkdir .ssh),
      %(echo "#{pub_key}" >> ~/.ssh/authorized_keys),
      %(passwd -l #{config[:username]})
    ])
  rescue
    @retries ||= 0
    if @retries < @max_retries
      info "Retrying connection..."
      sleep [2**(@retries - 1), @max_interval].min
      @retries += 1
      retry
    else
      raise
    end
  end
  info "Done setting up SSH access."
end
get_dc() click to toggle source
# File lib/kitchen/driver/linode.rb, line 103
def get_dc
  if config[:data_center].is_a? Integer
    data_center = compute.data_centers.find { |dc| dc.id == config[:data_center] }
  else
    data_center = compute.data_centers.find { |dc| dc.location =~ /#{config[:data_center]}/ }
  end
  
  if data_center.nil?
    fail(UserError, "No match for data_center: #{config[:data_center]}")
  end
  info "Got data center: #{data_center.location}..."
  return data_center
end
get_flavor() click to toggle source
# File lib/kitchen/driver/linode.rb, line 117
def get_flavor
  if config[:flavor].is_a? Integer
    if config[:flavor] < 1024
      flavor = compute.flavors.find { |f| f.id == config[:flavor] }
    else
      flavor = compute.flavors.find { |f| f.ram == config[:flavor] }
    end
  else
    flavor = compute.flavors.find { |f| f.name =~ /#{config[:flavor]}/ }
  end
  
  if flavor.nil?
    fail(UserError, "No match for flavor: #{config[:flavor]}")
  end
  info "Got flavor: #{flavor.name}..."
  return flavor
end
get_image() click to toggle source
# File lib/kitchen/driver/linode.rb, line 135
def get_image
  if config[:image].is_a? Integer
    image = compute.images.find { |i| i.id == config[:image] }
  else
    image = compute.images.find { |i| i.name =~ /#{config[:image]}/ }
  end
  if image.nil?
    fail(UserError, "No match for image: #{config[:image]}")
  end
  info "Got image: #{image.name}..."
  return image
end
get_kernel() click to toggle source
# File lib/kitchen/driver/linode.rb, line 148
def get_kernel
  if config[:kernel].is_a? Integer
    kernel = compute.kernels.find { |k| k.id == config[:kernel] }
  else
    kernel = compute.kernels.find { |k| k.name =~ /#{config[:kernel]}/ }
  end
  if kernel.nil?
    fail(UserError, "No match for kernel: #{config[:kernel]}")
  end
  info "Got kernel: #{kernel.name}..."
  return kernel
end
set_password() click to toggle source

ensure a password is set

# File lib/kitchen/driver/linode.rb, line 246
def set_password
  if config[:password].nil?
    config[:password] = [*('a'..'z'),*('A'..'Z'),*('0'..'9')].sample(15).join
  end
end
set_ssh_keys() click to toggle source

set ssh keys

# File lib/kitchen/driver/linode.rb, line 253
def set_ssh_keys
  if config[:private_key_path]
    config[:private_key_path] = File.expand_path(config[:private_key_path])
  end
  if config[:public_key_path]
    config[:public_key_path] = File.expand_path(config[:public_key_path])
  end
end
setup_ssh(state) click to toggle source
# File lib/kitchen/driver/linode.rb, line 180
def setup_ssh(state)
  set_ssh_keys
  state[:ssh_key] = config[:private_key_path]
  do_ssh_setup(state, config)
end