class Cyclid::API::Plugins::Digitalocean
Digitalocean
builder. Uses the Digitalocean
API
to obtain a build host instance.
Public Class Methods
new()
click to toggle source
# File lib/cyclid/plugins/builder/digitalocean.rb, line 34 def initialize @config = load_digitalocean_config(Cyclid.config.plugins) @client = DropletKit::Client.new(access_token: @config[:access_token]) end
Public Instance Methods
get(args = {})
click to toggle source
Create & return a build host
# File lib/cyclid/plugins/builder/digitalocean.rb, line 40 def get(args = {}) args.symbolize_keys! Cyclid.logger.debug "digitalocean: args=#{args}" # If there is one, split the 'os' into a 'distro' and 'release' if args.key? :os match = args[:os].match(/\A(\w*)_(.*)\Z/) distro = match[1] if match release = match[2] if match else # No OS was specified; use the default # XXX Defaults should be configurable distro = 'ubuntu' release = 'trusty' end # Convert Debian & Ubuntu release codenames release_version = if distro == 'ubuntu' or distro == 'debian' codename_to_version(release) else release end begin # Find, or create, the SSH key Cyclid can use build_key = build_ssh_key # Create the Droplet droplet = DropletKit::Droplet.new(name: create_name, region: @config[:region], image: "#{distro}-#{release_version}-x64", size: @config[:size], ssh_keys: [build_key.id]) created = @client.droplets.create droplet # Wait for the droplet to become 'active' created = wait_for_droplet(created) # Create a buildhost from the active Droplet details buildhost = DigitaloceanHost.new(name: created.name, host: created.networks.v4.first.ip_address, id: created.id, username: 'root', workspace: '/root', key: @config[:ssh_private_key], distro: distro, release: release) rescue StandardError => ex Cyclid.logger.error "couldn't get a build host from Digitalocean: #{ex}" raise "digitalocean failed: #{ex}" end Cyclid.logger.debug "digitalocean buildhost=#{buildhost.inspect}" return buildhost end
release(_transport, buildhost)
click to toggle source
Destroy the build host
# File lib/cyclid/plugins/builder/digitalocean.rb, line 98 def release(_transport, buildhost) @client.droplets.delete(id: buildhost[:id]) rescue StandardError => ex Cyclid.logger.error "Digitalcoean destroy timed out: #{ex}" end
Private Instance Methods
build_ssh_key()
click to toggle source
# File lib/cyclid/plugins/builder/digitalocean.rb, line 154 def build_ssh_key # Find the build key, if it exists build_key = nil all_keys = @client.ssh_keys.all all_keys.each do |key| build_key = key if key.name == @config[:ssh_key_name] end Cyclid.logger.debug "build_key=#{build_key.inspect}" # If the key doesn't exist, create it if build_key.nil? pubkey = File.read(@config[:ssh_public_key]) key = DropletKit::SSHKey.new(name: @config[:ssh_key_name], public_key: pubkey) build_key = @client.ssh_keys.create(key) Cyclid.logger.debug "build_key=#{build_key.inspect}" end return build_key end
codename_to_version(release)
click to toggle source
Convert Ubuntu & Debian release codenames to Digitialocean approved release versions
# File lib/cyclid/plugins/builder/digitalocean.rb, line 137 def codename_to_version(release) versions = { 'precise' => '12-04', 'trusty' => '14-04', 'xenial' => '16-04', 'yakkety' => '16-10', 'wheezy' => '7', 'jessie' => '8' } # No need to convert if it isn't a codename return release if release =~ /\A\d*[-\d*]/ raise "don't know what version Ubuntu/Debian #{release} is" \ unless versions.key? release return versions[release] end
create_name()
click to toggle source
# File lib/cyclid/plugins/builder/digitalocean.rb, line 197 def create_name base = @config[:instance_name] "#{base}-#{SecureRandom.hex(16)}" end
load_digitalocean_config(config)
click to toggle source
Load the config for the Digitalocean
plugin and set defaults if they're not in the config
# File lib/cyclid/plugins/builder/digitalocean.rb, line 111 def load_digitalocean_config(config) config.symbolize_keys! do_config = config[:digitalocean] || {} do_config.symbolize_keys! Cyclid.logger.debug "config=#{do_config}" raise 'the Digitalocean API access token must be provided' \ unless do_config.key? :access_token # Set defaults do_config[:region] = 'nyc1' unless do_config.key? :region do_config[:size] = '512mb' unless do_config.key? :size do_config[:ssh_private_key] = File.join(%w(/ etc cyclid id_rsa_build)) \ unless do_config.key? :ssh_private_key do_config[:ssh_public_key] = File.join(%w(/ etc cyclid id_rsa_build.pub)) \ unless do_config.key? :ssh_public_key do_config[:ssh_key_name] = 'cyclid-build' \ unless do_config.key? :ssh_key_name do_config[:instance_name] = 'cyclid-build' \ unless do_config.key? :instance_name return do_config end
wait_for_droplet(created)
click to toggle source
# File lib/cyclid/plugins/builder/digitalocean.rb, line 175 def wait_for_droplet(created) # Wait for the droplet to become active; wait a maximum of 1 minute, # polling every 2 seconds. Cyclid.logger.debug "Waiting for instance #{created.id} to become 'active'..." 29.times do created = @client.droplets.find(id: created.id.to_s) break if created.status == 'active' sleep 2 end Cyclid.logger.debug "created=#{created.inspect}" unless created.status == 'active' @client.droplets.delete(id: created.id) raise 'failed to create build host: did not become active within 1 minute. ' \ "Status is #{created.status}" \ end return created end