1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00

digitalocean supports bootstrap

This commit is contained in:
Trae Robrock 2013-07-21 11:09:53 -07:00
parent 8dee42d23b
commit e47f95b5f9
8 changed files with 84 additions and 18 deletions

1
.gitignore vendored
View file

@ -21,3 +21,4 @@ pkg
spec/credentials.yml spec/credentials.yml
vendor/* vendor/*
tags tags
tests/digitalocean/fixtures/

View file

@ -16,9 +16,11 @@ module Fog
attribute :flavor_id, :aliases => 'size_id' attribute :flavor_id, :aliases => 'size_id'
# Not documented in their API, but # Not documented in their API, but
# available nevertheless # available nevertheless
attribute :ip_address attribute :public_ip_address, :aliases => 'ip_address'
attribute :backups_active attribute :backups_active
attr_writer :ssh_keys
# Reboot the server (soft reboot). # Reboot the server (soft reboot).
# #
# The preferred method of rebooting a server. # The preferred method of rebooting a server.
@ -72,6 +74,25 @@ module Fog
service.power_on_server self.id service.power_on_server self.id
end end
def setup(credentials = {})
requires :public_ip_address
require 'net/ssh'
commands = [
%{mkdir .ssh},
%{passwd -l #{username}},
%{echo "#{Fog::JSON.encode(Fog::JSON.sanitize(attributes))}" >> ~/attributes.json}
]
if public_key
commands << %{echo "#{public_key}" >> ~/.ssh/authorized_keys}
end
# wait for aws to be ready
wait_for { sshable?(credentials) }
Fog::SSH.new(public_ip_address, username, credentials).run(commands)
end
# Creates the server (not to be called directly). # Creates the server (not to be called directly).
# #
# Usually called by Fog::Collection#create # Usually called by Fog::Collection#create
@ -94,6 +115,8 @@ module Fog
options = {} options = {}
if attributes[:ssh_key_ids] if attributes[:ssh_key_ids]
options[:ssh_key_ids] = attributes[:ssh_key_ids] options[:ssh_key_ids] = attributes[:ssh_key_ids]
elsif @ssh_keys
options[:ssh_key_ids] = @ssh_keys.map(&:id)
end end
data = service.create_server name, data = service.create_server name,
flavor_id, flavor_id,

View file

@ -6,16 +6,39 @@ module Fog
class DigitalOcean class DigitalOcean
class Servers < Fog::Collection class Servers < Fog::Collection
model Fog::Compute::DigitalOcean::Server model Fog::Compute::DigitalOcean::Server
def all(filters = {}) def all(filters = {})
load service.list_servers.body['droplets'] data = service.list_servers.body['droplets']
load(data)
end
def bootstrap(new_attributes = {})
server = new(new_attributes)
raise(ArgumentError, "public_key_path is required to configure the server.") unless new_attributes[:public_key_path]
raise(ArgumentError, "private_key_path is required to configure the server.") unless new_attributes[:private_key_path]
credential = Fog.respond_to?(:credential) && Fog.credential || :default
name = "fog_#{credential}"
ssh_key = service.ssh_keys.detect { |key| key.name == name }
if ssh_key.nil?
ssh_key = service.ssh_keys.create(
:name => name,
:ssh_pub_key => File.read(new_attributes[:public_key_path])
)
end
server.ssh_keys = [ssh_key]
server.save
server.wait_for { ready? }
server.setup :keys => [new_attributes[:private_key_path]]
server
end end
def get(id) def get(id)
if server = service.get_server_details(id).body['droplet'] server = service.get_server_details(id).body['droplet']
new server new(server) if server
end
rescue Fog::Errors::NotFound rescue Fog::Errors::NotFound
nil nil
end end

View file

@ -15,9 +15,8 @@ module Fog
end end
def get(uri) def get(uri)
if data = service.get_ssh_key(uri) data = service.get_ssh_key(uri).body['ssh_key']
new(data.body) new(data)
end
rescue Fog::Errors::NotFound rescue Fog::Errors::NotFound
nil nil
end end

View file

@ -6,9 +6,9 @@ module Fog
# #
# FIXME: missing ssh keys support # FIXME: missing ssh keys support
# #
def create_server( name, def create_server( name,
size_id, size_id,
image_id, image_id,
region_id, region_id,
options = {} ) options = {} )
@ -20,9 +20,10 @@ module Fog
} }
if options[:ssh_key_ids] if options[:ssh_key_ids]
options[:ssh_key_ids] = options[:ssh_key_ids].join(",") if options[:ssh_key_ids].is_a? Array
query_hash[:ssh_key_ids] = options[:ssh_key_ids] query_hash[:ssh_key_ids] = options[:ssh_key_ids]
end end
request( request(
:expects => [200], :expects => [200],
:method => 'GET', :method => 'GET',
@ -35,9 +36,9 @@ module Fog
class Mock class Mock
def create_server( name, def create_server( name,
size_id, size_id,
image_id, image_id,
region_id, region_id,
options = {} ) options = {} )
response = Excon::Response.new response = Excon::Response.new

View file

@ -16,6 +16,7 @@ Shindo.tests("Fog::Compute[:digitalocean] | server model", ['digitalocean', 'com
test(action) { server.respond_to? action } test(action) { server.respond_to? action }
end end
end end
tests('have attributes') do tests('have attributes') do
model_attribute_hash = server.attributes model_attribute_hash = server.attributes
attributes = [ attributes = [
@ -26,7 +27,8 @@ Shindo.tests("Fog::Compute[:digitalocean] | server model", ['digitalocean', 'com
:ip_address, :ip_address,
:flavor_id, :flavor_id,
:region_id, :region_id,
:image_id :image_id,
:ssh_keys=
] ]
tests("The server model should respond to") do tests("The server model should respond to") do
attributes.each do |attribute| attributes.each do |attribute|
@ -34,12 +36,14 @@ Shindo.tests("Fog::Compute[:digitalocean] | server model", ['digitalocean', 'com
end end
end end
end end
test('#reboot') do test('#reboot') do
pending if Fog.mocking? pending if Fog.mocking?
server.reboot server.reboot
server.wait_for { server.state == 'off' } server.wait_for { server.state == 'off' }
server.state == 'off' server.state == 'off'
end end
test('#power_cycle') do test('#power_cycle') do
pending if Fog.mocking? pending if Fog.mocking?
server.wait_for { server.ready? } server.wait_for { server.ready? }
@ -47,16 +51,19 @@ Shindo.tests("Fog::Compute[:digitalocean] | server model", ['digitalocean', 'com
server.wait_for { server.state == 'off' } server.wait_for { server.state == 'off' }
server.state == 'off' server.state == 'off'
end end
test('#stop') do test('#stop') do
server.stop server.stop
server.wait_for { server.state == 'off' } server.wait_for { server.state == 'off' }
server.state == 'off' server.state == 'off'
end end
test('#start') do test('#start') do
server.start server.start
server.wait_for { ready? } server.wait_for { ready? }
server.ready? server.ready?
end end
# DigitalOcean shutdown is unreliable # DigitalOcean shutdown is unreliable
# so disable it in real mode for now # so disable it in real mode for now
test('#shutdown') do test('#shutdown') do
@ -67,6 +74,7 @@ Shindo.tests("Fog::Compute[:digitalocean] | server model", ['digitalocean', 'com
server.wait_for { server.state == 'off' } server.wait_for { server.state == 'off' }
server.state == 'off' server.state == 'off'
end end
test('#update') do test('#update') do
begin begin
server.update server.update
@ -74,11 +82,11 @@ Shindo.tests("Fog::Compute[:digitalocean] | server model", ['digitalocean', 'com
true true
end end
end end
end end
# restore server state # restore server state
server.start server.start
server.wait_for { ready? }
end end

View file

@ -9,4 +9,13 @@ Shindo.tests('Fog::Compute[:digitalocean] | servers collection', ['digitalocean'
@instance.wait_for { ready? } @instance.wait_for { ready? }
end end
tests("#bootstrap").succeeds do
pending if Fog.mocking?
@server = service.servers.bootstrap({
:public_key_path => File.join(File.dirname(__FILE__), '../../fixtures/id_rsa.pub'),
:private_key_path => File.join(File.dirname(__FILE__), '../../fixtures/id_rsa')
}.merge(options))
end
@server.destroy if @server
end end

View file

@ -19,7 +19,9 @@ Shindo.tests('Fog::Compute[:digitalocean] | ssh_keys collection', ['digitalocean
tests('should be able to get a model') do tests('should be able to get a model') do
test('by instance id') do test('by instance id') do
service.ssh_keys.get(key.id).kind_of? Fog::Compute::DigitalOcean::SshKey retrieved_key = service.ssh_keys.get(key.id)
test { retrieved_key.kind_of? Fog::Compute::DigitalOcean::SshKey }
test { retrieved_key.name == key.name }
end end
end end