class Kitchen::Driver::Digitalocean

Digital Ocean driver for Kitchen.

@author Greg Fitzgerald <greg@gregf.org>

Constants

PLATFORM_SLUG_MAP

Public Instance Methods

create(state) click to toggle source
# File lib/kitchen/driver/digitalocean.rb, line 81
def create(state)
  server = create_server

  state[:server_id] = server.id

  info("DigitalOcean instance <#{state[:server_id]}> created.")

  loop do
    sleep 8
    droplet = client.droplets.find(id: state[:server_id])

    break if droplet && droplet.networks[:v4] &&
      droplet.networks[:v4].any? { |n| n[:type] == "public" }
  end
  droplet ||= client.droplets.find(id: state[:server_id])

  state[:hostname] = droplet.networks[:v4]
    .find { |n| n[:type] == "public" }["ip_address"]

  if config[:firewalls]
    debug("trying to add the firewall by id")
    fw_ids = if config[:firewalls].is_a?(String)
               config[:firewalls].split(/\s+|,\s+|,+/)
             elsif config[:firewalls].is_a?(Array)
               config[:firewalls]
             else
               warn("firewalls attribute is not string/array, ignoring")
               []
             end
    debug("firewall : #{YAML.dump(fw_ids.inspect)}")
    fw_ids.each do |fw_id|
      firewall = client.firewalls.find(id: fw_id)
      if firewall
        client.firewalls
          .add_droplets([droplet.id], id: firewall.id)
        debug("firewall added: #{firewall.id}")
      else
        warn("firewalls id: '#{fw_id}' was not found in api, ignoring")
      end
    end
  end

  wait_for_sshd(state[:hostname]); print "(ssh ready)\n"
  debug("digitalocean:create #{state[:hostname]}")
end
default_image() click to toggle source

This method attempts to fetch the platform from a list of well-known platform => slug mappings, and falls back to using just the platform as provided if it can’t find a mapping.

# File lib/kitchen/driver/digitalocean.rb, line 155
def default_image
  PLATFORM_SLUG_MAP.fetch(instance.platform.name,
                          instance.platform.name)
end
default_name() click to toggle source

Generate what should be a unique server name up to 63 total chars Base name: 15 Username: 15 Hostname: 23 Random string: 7 Separators: 3

Total: 63

# File lib/kitchen/driver/digitalocean.rb, line 168
def default_name
  [
    instance.name.gsub(/\W/, "")[0..14],
    (Etc.getlogin || "nologin").gsub(/\W/, "")[0..14],
    Socket.gethostname.gsub(/\W/, "")[0..22],
    Array.new(7) { rand(36).to_s(36) }.join,
  ].join("-").tr("_", "-")
end
destroy(state) click to toggle source
# File lib/kitchen/driver/digitalocean.rb, line 127
def destroy(state)
  return if state[:server_id].nil?

  # A new droplet cannot be destroyed before it is active
  # Retry destroying the droplet as long as its status is "new"
  loop do
    droplet = client.droplets.find(id: state[:server_id])

    break unless droplet

    if droplet.status != "new"
      client.droplets.delete(id: state[:server_id])
      break
    end

    info("Waiting on DigitalOcean instance <#{state[:server_id]}>
         to be active to destroy it, retrying in 8 seconds")
    sleep 8
  end

  info("DigitalOcean instance <#{state[:server_id]}> destroyed.")
  state.delete(:server_id)
  state.delete(:hostname)
end

Private Instance Methods

client() click to toggle source
# File lib/kitchen/driver/digitalocean.rb, line 179
def client
  debug_client_config

  DropletKit::Client.new(access_token: config[:digitalocean_access_token], api_url: config[:api_url])
end
create_server() click to toggle source
# File lib/kitchen/driver/digitalocean.rb, line 185
def create_server
  debug_server_config

  droplet = DropletKit::Droplet.new(
    name: config[:server_name],
    region: config[:region],
    image: config[:image],
    size: config[:size],
    monitoring: config[:monitoring],
    ssh_keys: config[:ssh_key_ids].to_s.split(/, ?/),
    private_networking: config[:private_networking],
    ipv6: config[:ipv6],
    user_data: config[:user_data],
    vpc_uuid: config[:vpcs],
    tags: if config[:tags].is_a?(String)
            config[:tags].split(/\s+|,\s+|,+/)
          else
            config[:tags]
          end
  )

  resp = client.droplets.create(droplet)

  if resp.class != DropletKit::Droplet
    error JSON.parse(resp)["message"]
    error "Please check your access token is set correctly."
  else
    resp
  end
end
debug_client_config() click to toggle source
# File lib/kitchen/driver/digitalocean.rb, line 231
def debug_client_config
  debug("digitalocean_api_key #{config[:digitalocean_access_token]}")
end
debug_server_config() click to toggle source
# File lib/kitchen/driver/digitalocean.rb, line 216
def debug_server_config
  debug("digitalocean:name #{config[:server_name]}")
  debug("digitalocean:image#{config[:image]}")
  debug("digitalocean:size #{config[:size]}")
  debug("digitalocean:monitoring #{config[:monitoring]}")
  debug("digitalocean:region #{config[:region]}")
  debug("digitalocean:ssh_key_ids #{config[:ssh_key_ids]}")
  debug("digitalocean:private_networking #{config[:private_networking]}")
  debug("digitalocean:ipv4 #{config[:ipv4]})")
  debug("digitalocean:ipv6 #{config[:ipv6]}")
  debug("digitalocean:user_data #{config[:user_data]}")
  debug("digitalocean:tags #{config[:tags]}")
  debug("digitalocean:firewalls #{config[:firewalls]}")
end