зеркало из https://github.com/microsoft/fog.git
Merge branch 'master' of github.com:fog/fog into json_lib
This commit is contained in:
Коммит
1fd1303977
|
@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|||
## the sub! line in the Rakefile
|
||||
s.name = 'fog'
|
||||
s.version = '1.10.0'
|
||||
s.date = '2013-03-05'
|
||||
s.date = '2013-03-30'
|
||||
s.rubyforge_project = 'fog'
|
||||
|
||||
## Make sure your summary is short. The description may be as long
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
# necessary when requiring fog without rubygems while also
|
||||
# maintaining ruby 1.8.7 support (can't use require_relative)
|
||||
__LIB_DIR__ = File.expand_path(File.dirname(__FILE__))
|
||||
$LOAD_PATH.unshift __LIB_DIR__ unless $LOAD_PATH.include?(__LIB_DIR__)
|
||||
|
||||
# any one of these can be required separately.
|
||||
# they all depend on fog/core for shared functionality.
|
||||
require 'fog/atmos'
|
||||
|
@ -6,6 +11,7 @@ require 'fog/bluebox'
|
|||
require 'fog/brightbox'
|
||||
require 'fog/cloudstack'
|
||||
require 'fog/clodo'
|
||||
require 'fog/digitalocean'
|
||||
require 'fog/dnsimple'
|
||||
require 'fog/dnsmadeeasy'
|
||||
require 'fog/dreamhost'
|
||||
|
|
|
@ -43,7 +43,7 @@ module Fog
|
|||
if INVALID_LOCATIONS.include?(new_location)
|
||||
raise ArgumentError, "location must not include any of #{INVALID_LOCATIONS.join(', ')}. See http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUT.html"
|
||||
else
|
||||
merge_attributes(:location => new_location)
|
||||
@location = new_location
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ require 'fog/bin/bluebox'
|
|||
require 'fog/bin/brightbox'
|
||||
require 'fog/bin/cloudstack'
|
||||
require 'fog/bin/clodo'
|
||||
require 'fog/bin/digitalocean'
|
||||
require 'fog/bin/dnsimple'
|
||||
require 'fog/bin/dnsmadeeasy'
|
||||
require 'fog/bin/dreamhost'
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
class DigitalOcean < Fog::Bin
|
||||
class << self
|
||||
|
||||
def class_for(key)
|
||||
case key
|
||||
when :compute
|
||||
Fog::Compute::DigitalOcean
|
||||
else
|
||||
raise ArgumentError, "Unsupported #{self} service: #{key}"
|
||||
end
|
||||
end
|
||||
|
||||
def [](service)
|
||||
@@connections ||= Hash.new do |hash, key|
|
||||
hash[key] = case key
|
||||
when :compute
|
||||
Fog::Logger.warning("DigitalOcean[:compute] is not recommended, use Compute[:digitalocean] for portability")
|
||||
Fog::Compute.new(:provider => 'DigitalOcean')
|
||||
else
|
||||
raise ArgumentError, "Unrecognized service: #{key.inspect}"
|
||||
end
|
||||
end
|
||||
@@connections[service]
|
||||
end
|
||||
|
||||
def services
|
||||
Fog::DigitalOcean.services
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -1,8 +1,3 @@
|
|||
__LIB_DIR__ = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
||||
|
||||
$LOAD_PATH.unshift __LIB_DIR__ unless
|
||||
$LOAD_PATH.include?(__LIB_DIR__)
|
||||
|
||||
# external core dependencies
|
||||
require 'base64'
|
||||
require 'cgi'
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
require 'fog/core'
|
||||
|
||||
module Fog
|
||||
module DigitalOcean
|
||||
extend Fog::Provider
|
||||
service(:compute, 'digitalocean/compute', 'Compute')
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
require 'fog/digitalocean'
|
||||
require 'fog/compute'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean < Fog::Service
|
||||
|
||||
requires :digitalocean_api_key
|
||||
requires :digitalocean_client_id
|
||||
|
||||
recognizes :digitalocean_api_url
|
||||
|
||||
model_path 'fog/digitalocean/models/compute'
|
||||
model :server
|
||||
collection :servers
|
||||
model :flavor
|
||||
collection :flavors
|
||||
model :image
|
||||
collection :images
|
||||
model :region
|
||||
collection :regions
|
||||
model :ssh_key
|
||||
collection :ssh_keys
|
||||
|
||||
request_path 'fog/digitalocean/requests/compute'
|
||||
request :list_servers
|
||||
request :list_images
|
||||
request :list_regions
|
||||
request :list_flavors
|
||||
request :get_server_details
|
||||
request :create_server
|
||||
request :destroy_server
|
||||
request :reboot_server
|
||||
request :power_cycle_server
|
||||
request :power_off_server
|
||||
request :power_on_server
|
||||
request :shutdown_server
|
||||
request :list_ssh_keys
|
||||
request :create_ssh_key
|
||||
request :get_ssh_key
|
||||
request :destroy_ssh_key
|
||||
|
||||
# request :digitalocean_resize
|
||||
|
||||
class Mock
|
||||
|
||||
def self.data
|
||||
@data ||= Hash.new do |hash, key|
|
||||
hash[key] = {
|
||||
:servers => [],
|
||||
:ssh_keys => []
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def self.reset
|
||||
@data = nil
|
||||
end
|
||||
|
||||
def initialize(options={})
|
||||
@digitalocean_api_key = options[:digitalocean_api_key]
|
||||
end
|
||||
|
||||
def data
|
||||
self.class.data[@digitalocean_api_key]
|
||||
end
|
||||
|
||||
def reset_data
|
||||
self.class.data.delete(@digitalocean_api_key)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Real
|
||||
|
||||
def initialize(options={})
|
||||
@digitalocean_api_key = options[:digitalocean_api_key]
|
||||
@digitalocean_client_id = options[:digitalocean_client_id]
|
||||
@digitalocean_api_url = options[:digitalocean_api_url] || \
|
||||
"https://api.digitalocean.com"
|
||||
@connection = Fog::Connection.new(@digitalocean_api_url)
|
||||
end
|
||||
|
||||
def reload
|
||||
@connection.reset
|
||||
end
|
||||
|
||||
def request(params)
|
||||
params[:query] ||= {}
|
||||
params[:query].merge!(:api_key => @digitalocean_api_key)
|
||||
params[:query].merge!(:client_id => @digitalocean_client_id)
|
||||
|
||||
response = @connection.request(params)
|
||||
|
||||
unless response.body.empty?
|
||||
response.body = Fog::JSON.decode(response.body)
|
||||
if response.body['status'] != 'OK'
|
||||
raise Fog::Errors::Error.new response.body.to_s
|
||||
end
|
||||
end
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,106 @@
|
|||
# Getting started: the compute service
|
||||
|
||||
You'll need a DigitalOcean account and API key to use this provider.
|
||||
|
||||
Get one from http://www.digitalocean.com.
|
||||
|
||||
To generate the API key, login to the DigitalOcean web panel and go to
|
||||
'My Settings -> API Access -> Generate a new API key'.
|
||||
|
||||
Write down the Client Key and API Key, you'll need both to use the service.
|
||||
|
||||
|
||||
## Connecting, retrieving and managing server objects
|
||||
|
||||
Before we start, I guess it will be useful to the reader to know
|
||||
that Fog servers are 'droplets' in DigitalOcean's parlance.
|
||||
'Server' is the Fog way to name VMs, and we have
|
||||
respected that in the DigitalOcean's Fog provider.
|
||||
|
||||
First, create a connection to the host:
|
||||
|
||||
```ruby
|
||||
require 'fog'
|
||||
|
||||
do = Fog::Compute.new({
|
||||
:provider => 'DigitalOcean',
|
||||
:digitalocean_api_key => 'poiuweoruwoeiuroiwuer', # your API key here
|
||||
:digitalocean_client_id => 'lkjasoidfuoiu' # your client key here
|
||||
})
|
||||
```
|
||||
|
||||
## Listing servers
|
||||
|
||||
Listing servers and attributes:
|
||||
|
||||
```ruby
|
||||
docean.servers.each do |server|
|
||||
# remember, servers are droplets
|
||||
server.id
|
||||
server.name
|
||||
server.state
|
||||
server.backups_enabled
|
||||
server.image_id
|
||||
server.flavor_id # server 'size' in DigitalOcean's API parlance
|
||||
server.region_id
|
||||
end
|
||||
```
|
||||
|
||||
## Server creation and life-cycle management
|
||||
|
||||
Creating a new server (droplet):
|
||||
|
||||
```ruby
|
||||
server = docean.servers.create :name => 'foobar',
|
||||
# use the first image listed
|
||||
:image_id => docean.images.first.id,
|
||||
# use the first flavor listed
|
||||
:flavor_id => docean.flavors.first.id,
|
||||
# use the first region listed
|
||||
:region_id => docean.regions.first.id
|
||||
```
|
||||
|
||||
The server is automatically started after that.
|
||||
|
||||
We didn't pay attention when choosing the flavor, image and region used
|
||||
but you can easily list them too, and then decide:
|
||||
|
||||
```ruby
|
||||
docean.images.each do |image|
|
||||
image.id
|
||||
image.name
|
||||
image.distribution
|
||||
end
|
||||
|
||||
docean.flavors.each do |flavor|
|
||||
flavor.id
|
||||
flavor.name
|
||||
end
|
||||
|
||||
docean.regions.each do |region|
|
||||
region.id
|
||||
region.name
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
Rebooting a server:
|
||||
|
||||
```ruby
|
||||
server = docean.servers.first
|
||||
server.reboot
|
||||
```
|
||||
|
||||
Power cycle a server:
|
||||
|
||||
```ruby
|
||||
server.power_cycle
|
||||
```
|
||||
|
||||
Destroying the server:
|
||||
|
||||
```ruby
|
||||
server.destroy
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Flavor < Fog::Model
|
||||
|
||||
identity :id
|
||||
attribute :name
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/digitalocean/models/compute/flavor'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
|
||||
class Flavors < Fog::Collection
|
||||
model Fog::Compute::DigitalOcean::Flavor
|
||||
|
||||
def all
|
||||
load service.list_flavors.body['sizes']
|
||||
end
|
||||
|
||||
def get(id)
|
||||
all.find { |f| f.id == id }
|
||||
rescue Fog::Errors::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Image < Fog::Model
|
||||
|
||||
identity :id
|
||||
attribute :name
|
||||
attribute :distribution
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/digitalocean/models/compute/image'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
|
||||
class Images < Fog::Collection
|
||||
model Fog::Compute::DigitalOcean::Image
|
||||
|
||||
def all
|
||||
load service.list_images.body['images']
|
||||
end
|
||||
|
||||
def get(id)
|
||||
all.find { |f| f.id == id }
|
||||
rescue Fog::Errors::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Region < Fog::Model
|
||||
|
||||
identity :id
|
||||
attribute :name
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/digitalocean/models/compute/region'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
|
||||
class Regions < Fog::Collection
|
||||
model Fog::Compute::DigitalOcean::Region
|
||||
|
||||
def all
|
||||
load service.list_regions.body['regions']
|
||||
end
|
||||
|
||||
def get(id)
|
||||
all.find { |f| f.id == id }
|
||||
rescue Fog::Errors::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,150 @@
|
|||
require 'fog/compute/models/server'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
|
||||
# A DigitalOcean Droplet
|
||||
#
|
||||
class Server < Fog::Compute::Server
|
||||
|
||||
identity :id
|
||||
attribute :name
|
||||
attribute :state, :aliases => 'status'
|
||||
attribute :image_id
|
||||
attribute :region_id
|
||||
attribute :flavor_id, :aliases => 'size_id'
|
||||
# Not documented in their API, but
|
||||
# available nevertheless
|
||||
attribute :ip_address
|
||||
attribute :backups_active
|
||||
|
||||
# Reboot the server (soft reboot).
|
||||
#
|
||||
# The preferred method of rebooting a server.
|
||||
def reboot
|
||||
requires :id
|
||||
service.reboot_server self.id
|
||||
end
|
||||
|
||||
# Reboot the server (hard reboot).
|
||||
#
|
||||
# Powers the server off and then powers it on again.
|
||||
def power_cycle
|
||||
requires :id
|
||||
service.power_cycle_server self.id
|
||||
end
|
||||
|
||||
# Shutdown the server
|
||||
#
|
||||
# Sends a shutdown signal to the operating system.
|
||||
# The server consumes resources while powered off
|
||||
# so you are still charged.
|
||||
#
|
||||
# @see https://www.digitalocean.com/community/questions/am-i-charged-while-my-droplet-is-in-a-powered-off-state
|
||||
def shutdown
|
||||
requires :id
|
||||
service.shutdown_server self.id
|
||||
end
|
||||
|
||||
# Power off the server
|
||||
#
|
||||
# Works as a power switch.
|
||||
# The server consumes resources while powered off
|
||||
# so you are still charged.
|
||||
#
|
||||
# @see https://www.digitalocean.com/community/questions/am-i-charged-while-my-droplet-is-in-a-powered-off-state
|
||||
def stop
|
||||
requires :id
|
||||
service.power_off_server self.id
|
||||
end
|
||||
|
||||
# Power on the server.
|
||||
#
|
||||
# The server consumes resources while powered on
|
||||
# so you will be charged.
|
||||
#
|
||||
# Each time a server is spun up, even if for a few seconds,
|
||||
# it is charged for an hour.
|
||||
#
|
||||
def start
|
||||
requires :id
|
||||
service.power_on_server self.id
|
||||
end
|
||||
|
||||
# Creates the server (not to be called directly).
|
||||
#
|
||||
# Usually called by Fog::Collection#create
|
||||
#
|
||||
# do = Fog::Compute.new({
|
||||
# :provider => 'DigitalOcean',
|
||||
# :digitalocean_api_key => 'key-here', # your API key here
|
||||
# :digitalocean_client_id => 'client-id-here' # your client key here
|
||||
# })
|
||||
# do.servers.create :name => 'foobar',
|
||||
# :image_id => image_id_here,
|
||||
# :flavor_id => flavor_id_here,
|
||||
# :region_id => region_id_here
|
||||
#
|
||||
# @return [Boolean]
|
||||
def save
|
||||
raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
|
||||
requires :name, :flavor_id, :image_id, :region_id
|
||||
|
||||
options = {}
|
||||
if attributes[:ssh_key_ids]
|
||||
options[:ssh_key_ids] = attributes[:ssh_key_ids]
|
||||
end
|
||||
data = service.create_server name,
|
||||
flavor_id,
|
||||
image_id,
|
||||
region_id,
|
||||
options
|
||||
merge_attributes(data.body['droplet'])
|
||||
true
|
||||
end
|
||||
|
||||
# Destroy the server, freeing up the resources.
|
||||
#
|
||||
# DigitalOcean will stop charging you for the resources
|
||||
# the server was using.
|
||||
#
|
||||
# Once the server has been destroyed, there's no way
|
||||
# to recover it so the data is irrecoverably lost.
|
||||
#
|
||||
# IMPORTANT: As of 2013/01/31, you should wait some time to
|
||||
# destroy the server after creating it. If you try to destroy
|
||||
# the server too fast, the destroy event may be lost and the
|
||||
# server will remain running and consuming resources, so
|
||||
# DigitalOcean will keep charging you.
|
||||
# Double checked this with DigitalOcean staff and confirmed
|
||||
# that it's the way it works right now.
|
||||
#
|
||||
# Double check the server has been destroyed!
|
||||
def destroy
|
||||
requires :id
|
||||
service.destroy_server id
|
||||
end
|
||||
|
||||
# Checks whether the server status is 'active'.
|
||||
#
|
||||
# The server transitions from 'new' to 'active' sixty to ninety
|
||||
# seconds after creating it (time varies and may take more
|
||||
# than 90 secs).
|
||||
#
|
||||
# @return [Boolean]
|
||||
def ready?
|
||||
state == 'active'
|
||||
end
|
||||
|
||||
# DigitalOcean API does not support updating server state
|
||||
def update
|
||||
msg = 'DigitalOcean servers do not support updates'
|
||||
raise NotImplementedError.new(msg)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/digitalocean/models/compute/server'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
|
||||
class Servers < Fog::Collection
|
||||
model Fog::Compute::DigitalOcean::Server
|
||||
|
||||
def all(filters = {})
|
||||
load service.list_servers.body['droplets']
|
||||
end
|
||||
|
||||
def get(id)
|
||||
if server = service.get_server_details(id).body['droplet']
|
||||
new server
|
||||
end
|
||||
rescue Fog::Errors::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class SshKey < Fog::Model
|
||||
|
||||
identity :id
|
||||
|
||||
attribute :name
|
||||
attribute :ssh_pub_key
|
||||
|
||||
def save
|
||||
requires :name, :ssh_pub_key
|
||||
|
||||
merge_attributes(service.create_ssh_key(name, ssh_pub_key).body['ssh_key'])
|
||||
true
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :id
|
||||
|
||||
service.destroy_ssh_key id
|
||||
true
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
require 'fog/digitalocean/models/compute/ssh_key'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class SshKeys < Fog::Collection
|
||||
|
||||
identity :href
|
||||
|
||||
model Fog::Compute::DigitalOcean::SshKey
|
||||
|
||||
def all
|
||||
data = service.list_ssh_keys.body['ssh_keys']
|
||||
load(data)
|
||||
end
|
||||
|
||||
def get(uri)
|
||||
if data = service.get_ssh_key(uri)
|
||||
new(data.body)
|
||||
end
|
||||
rescue Fog::Errors::NotFound
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
#
|
||||
# FIXME: missing ssh keys support
|
||||
#
|
||||
def create_server( name,
|
||||
size_id,
|
||||
image_id,
|
||||
region_id,
|
||||
options = {} )
|
||||
|
||||
query_hash = {
|
||||
:name => name,
|
||||
:size_id => size_id,
|
||||
:image_id => image_id,
|
||||
:region_id => region_id
|
||||
}
|
||||
|
||||
if options[:ssh_key_ids]
|
||||
query_hash[:ssh_key_ids] = options[:ssh_key_ids]
|
||||
end
|
||||
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => 'droplets/new',
|
||||
:query => query_hash
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def create_server( name,
|
||||
size_id,
|
||||
image_id,
|
||||
region_id,
|
||||
options = {} )
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
|
||||
mock_data = {
|
||||
"id" => Fog::Mock.random_numbers(1).to_i,
|
||||
"event_id" => Fog::Mock.random_numbers(2).to_i,
|
||||
"name" => name,
|
||||
"size_id" => size_id,
|
||||
"image_id" => image_id,
|
||||
"region_id" => region_id,
|
||||
"status" => 'active'
|
||||
}
|
||||
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
"droplet" => mock_data
|
||||
}
|
||||
|
||||
self.data[:servers] << mock_data
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def create_ssh_key( name, pub_key )
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => 'ssh_keys/new',
|
||||
:query => { 'name' => name, 'ssh_pub_key' => pub_key }
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def create_ssh_key( name, pub_key )
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
mock_data = {
|
||||
"id" => Fog::Mock.random_numbers(1).to_i,
|
||||
"name" => name,
|
||||
"ssh_pub_key" => pub_key
|
||||
}
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
"ssh_key" => mock_data
|
||||
}
|
||||
self.data[:ssh_keys] << mock_data
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
#
|
||||
# FIXME: missing ssh keys support
|
||||
#
|
||||
def destroy_server( id )
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "droplets/#{id}/destroy"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def destroy_server( id )
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
response.body = {
|
||||
"event_id" => Fog::Mock.random_numbers(1).to_i,
|
||||
"status" => "OK"
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,37 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
#
|
||||
# Delete a SSH public key from your account
|
||||
#
|
||||
# @see https://www.digitalocean.com/api#ssh_keys
|
||||
#
|
||||
def destroy_ssh_key(id)
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "ssh_keys/#{id}/destroy"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def destroy_ssh_key(id)
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
if self.data[:ssh_keys].reject! { |k| k['id'] == id }
|
||||
response.body = { "status" => "OK" }
|
||||
else
|
||||
response.body = { "status" => "ERROR" }
|
||||
end
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def get_server_details(server_id)
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "droplets/#{server_id}"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def get_server_details(server_id)
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
|
||||
server = self.data[:servers].find { |s| s['id'] == server_id }
|
||||
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
"droplet" => self.data[:servers].find { |s| s['id'] == server_id }
|
||||
}
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,39 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
#
|
||||
# This method shows a specific public SSH key in your account
|
||||
# that can be added to a droplet.
|
||||
#
|
||||
# @see https://www.digitalocean.com/api#ssh_keys
|
||||
#
|
||||
def get_ssh_key(id)
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "ssh_keys/#{id}"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def get_ssh_key(id)
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
# key listing does not return ssh_pub_key
|
||||
# https://www.digitalocean.com/api#ssh_keys
|
||||
"ssh_key" => self.data[:ssh_keys].find { |k| k['id'] == id }
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def list_flavors(options = {})
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => 'sizes'
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def list_flavors
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
"sizes" => [
|
||||
{"id" => 33,"name" => "512MB"},
|
||||
{"id" => 34,"name" => "1GB"},
|
||||
{"id" => 35,"name" => "2GB"},
|
||||
{"id" => 36,"name" => "4GB"},
|
||||
{"id" => 37,"name" => "8GB"},
|
||||
{"id" => 38,"name" => "16GB"}
|
||||
]
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,49 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def list_images(options = {})
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => 'images'
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def list_images
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
"images" => [
|
||||
# Sample image
|
||||
{
|
||||
"id" => 1601,
|
||||
"name" => "CentOS 5.8 x64",
|
||||
"distribution" => "CentOS"
|
||||
},
|
||||
{
|
||||
"id" => 1602,
|
||||
"name" => "CentOS 5.8 x32",
|
||||
"distribution" => "CentOS"
|
||||
},
|
||||
{
|
||||
"id" => 2676,
|
||||
"name" => "Ubuntu 12.04 x64 Server",
|
||||
"distribution" => "Ubuntu"
|
||||
},
|
||||
|
||||
]
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def list_regions(options = {})
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => 'regions'
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def list_regions
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
"regions" => [
|
||||
{"id" => 1,"name" => "New York 1"},
|
||||
{"id" => 2,"name" => "Amsterdam 1"}
|
||||
]
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def list_servers(options = {})
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => 'droplets'
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def list_servers
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
"droplets" => self.data[:servers]
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def list_ssh_keys(options = {})
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => 'ssh_keys'
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def list_ssh_keys
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
response.body = {
|
||||
"status" => "OK",
|
||||
"ssh_keys" => self.data[:ssh_keys]
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def power_cycle_server( id )
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "droplets/#{id}/power_cycle"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def power_cycle_server( id )
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
server = self.data[:servers].find { |s| s['id'] == id }
|
||||
server['status'] = 'off' if server
|
||||
response.body = {
|
||||
"event_id" => Fog::Mock.random_numbers(1).to_i,
|
||||
"status" => "OK"
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def power_off_server( id )
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "droplets/#{id}/power_off"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def power_off_server( id )
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
server = self.data[:servers].find { |s| s['id'] }
|
||||
server['status'] = 'off' if server
|
||||
response.body = {
|
||||
"event_id" => Fog::Mock.random_numbers(1).to_i,
|
||||
"status" => "OK"
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def power_on_server( id )
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "droplets/#{id}/power_on"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def power_on_server( id )
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
server = self.data[:servers].find { |s| s['id'] }
|
||||
server['status'] = 'active' if server
|
||||
response.body = {
|
||||
"event_id" => Fog::Mock.random_numbers(1).to_i,
|
||||
"status" => "OK"
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def reboot_server( id )
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "droplets/#{id}/reboot"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def reboot_server( id )
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
server = self.data[:servers].find { |s| s['id'] == id }
|
||||
server['status'] = 'off' if server
|
||||
response.body = {
|
||||
"event_id" => Fog::Mock.random_numbers(1).to_i,
|
||||
"status" => "OK"
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class DigitalOcean
|
||||
class Real
|
||||
|
||||
def shutdown_server( id )
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "droplets/#{id}/shutdown"
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Mock
|
||||
|
||||
def shutdown_server( id )
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
server = self.data[:servers].find { |s| s['id'] == id }
|
||||
|
||||
# Simulate reboot
|
||||
server['status'] = 'off' if server
|
||||
|
||||
response.body = {
|
||||
"event_id" => Fog::Mock.random_numbers(1).to_i,
|
||||
"status" => "OK"
|
||||
}
|
||||
response
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
# Shortcut for Fog::Compute[:digitalocean]
|
||||
def service
|
||||
Fog::Compute[:digitalocean]
|
||||
end
|
||||
|
||||
# Create a long lived server for the tests
|
||||
def fog_test_server
|
||||
server = service.servers.find { |s| s.name == 'fog-test-server' }
|
||||
unless server
|
||||
image = service.images.find { |i| i.name == 'Ubuntu 12.04 x64 Server' }
|
||||
region = service.regions.find { |r| r.name == 'New York 1' }
|
||||
flavor = service.flavors.find { |r| r.name == '512MB' }
|
||||
server = service.servers.create :name => 'fog-test-server',
|
||||
:image_id => image.id,
|
||||
:region_id => region.id,
|
||||
:flavor_id => flavor.id
|
||||
# Wait for the server to come up
|
||||
begin
|
||||
server.wait_for(120) { server.reload rescue nil; server.ready? }
|
||||
rescue Fog::Errors::TimeoutError
|
||||
# Server bootstrap took more than 120 secs!
|
||||
end
|
||||
end
|
||||
server
|
||||
end
|
||||
|
||||
# Destroy the long lived server
|
||||
def fog_test_server_destroy
|
||||
server = service.servers.find { |s| s.name == 'fog-test-server' }
|
||||
server.destroy if server
|
||||
end
|
||||
|
||||
at_exit do
|
||||
unless Fog.mocking?
|
||||
server = service.servers.find { |s| s.name == 'fog-test-server' }
|
||||
if server
|
||||
server.wait_for(120) do
|
||||
reload rescue nil; ready?
|
||||
end
|
||||
end
|
||||
fog_test_server_destroy
|
||||
end
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
Shindo.tests("Fog::Compute[:digitalocean] | flavor model", ['digitalocean', 'compute']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
flavor = service.flavors.first
|
||||
|
||||
tests('The flavor model should') do
|
||||
tests('have the action') do
|
||||
test('reload') { flavor.respond_to? 'reload' }
|
||||
end
|
||||
tests('have attributes') do
|
||||
model_attribute_hash = flavor.attributes
|
||||
attributes = [
|
||||
:id,
|
||||
:name,
|
||||
]
|
||||
tests("The flavor model should respond to") do
|
||||
attributes.each do |attribute|
|
||||
test("#{attribute}") { flavor.respond_to? attribute }
|
||||
end
|
||||
end
|
||||
tests("The attributes hash should have key") do
|
||||
attributes.each do |attribute|
|
||||
test("#{attribute}") { model_attribute_hash.has_key? attribute }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
Shindo.tests("Fog::Compute[:digitalocean] | image model", ['digitalocean', 'compute']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
image = service.images.first
|
||||
|
||||
tests('The image model should') do
|
||||
tests('have the action') do
|
||||
test('reload') { image.respond_to? 'reload' }
|
||||
end
|
||||
tests('have attributes') do
|
||||
model_attribute_hash = image.attributes
|
||||
attributes = [
|
||||
:id,
|
||||
:name,
|
||||
:distribution
|
||||
]
|
||||
tests("The image model should respond to") do
|
||||
attributes.each do |attribute|
|
||||
test("#{attribute}") { image.respond_to? attribute }
|
||||
end
|
||||
end
|
||||
tests("The attributes hash should have key") do
|
||||
attributes.each do |attribute|
|
||||
test("#{attribute}") { model_attribute_hash.has_key? attribute }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
Shindo.tests("Fog::Compute[:digitalocean] | region model", ['digitalocean', 'compute']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
region = service.regions.first
|
||||
|
||||
tests('The region model should') do
|
||||
tests('have the action') do
|
||||
test('reload') { region.respond_to? 'reload' }
|
||||
end
|
||||
tests('have attributes') do
|
||||
model_attribute_hash = region.attributes
|
||||
attributes = [
|
||||
:id,
|
||||
:name,
|
||||
]
|
||||
tests("The region model should respond to") do
|
||||
attributes.each do |attribute|
|
||||
test("#{attribute}") { region.respond_to? attribute }
|
||||
end
|
||||
end
|
||||
tests("The attributes hash should have key") do
|
||||
attributes.each do |attribute|
|
||||
test("#{attribute}") { model_attribute_hash.has_key? attribute }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
Shindo.tests("Fog::Compute[:digitalocean] | server model", ['digitalocean', 'compute']) do
|
||||
|
||||
server = fog_test_server
|
||||
|
||||
tests('The server model should') do
|
||||
|
||||
tests('have the action') do
|
||||
test('reload') { server.respond_to? 'reload' }
|
||||
%w{
|
||||
shutdown
|
||||
reboot
|
||||
power_cycle
|
||||
stop
|
||||
start
|
||||
}.each do |action|
|
||||
test(action) { server.respond_to? action }
|
||||
end
|
||||
end
|
||||
tests('have attributes') do
|
||||
model_attribute_hash = server.attributes
|
||||
attributes = [
|
||||
:id,
|
||||
:name,
|
||||
:state,
|
||||
:backups_active,
|
||||
:ip_address,
|
||||
:flavor_id,
|
||||
:region_id,
|
||||
:image_id
|
||||
]
|
||||
tests("The server model should respond to") do
|
||||
attributes.each do |attribute|
|
||||
test("#{attribute}") { server.respond_to? attribute }
|
||||
end
|
||||
end
|
||||
end
|
||||
test('#reboot') do
|
||||
pending if Fog.mocking?
|
||||
server.reboot
|
||||
server.wait_for { server.state == 'off' }
|
||||
server.state == 'off'
|
||||
end
|
||||
test('#power_cycle') do
|
||||
pending if Fog.mocking?
|
||||
server.wait_for { server.ready? }
|
||||
server.power_cycle
|
||||
server.wait_for { server.state == 'off' }
|
||||
server.state == 'off'
|
||||
end
|
||||
test('#stop') do
|
||||
server.stop
|
||||
server.wait_for { server.state == 'off' }
|
||||
server.state == 'off'
|
||||
end
|
||||
test('#start') do
|
||||
server.start
|
||||
server.wait_for { ready? }
|
||||
server.ready?
|
||||
end
|
||||
# DigitalOcean shutdown is unreliable
|
||||
# so disable it in real mode for now
|
||||
test('#shutdown') do
|
||||
pending unless Fog.mocking?
|
||||
server.start
|
||||
server.wait_for { server.ready? }
|
||||
server.shutdown
|
||||
server.wait_for { server.state == 'off' }
|
||||
server.state == 'off'
|
||||
end
|
||||
test('#update') do
|
||||
begin
|
||||
server.update
|
||||
rescue NotImplementedError => e
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# restore server state
|
||||
server.start
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | servers collection', ['digitalocean']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
|
||||
tests('The servers collection') do
|
||||
servers = service.servers.all
|
||||
|
||||
server = fog_test_server
|
||||
|
||||
test('should NOT be empty') do
|
||||
servers.reload
|
||||
!servers.empty?
|
||||
end
|
||||
|
||||
test('should be a kind of Fog::Compute::DigitalOcean::Servers') do
|
||||
servers.kind_of? Fog::Compute::DigitalOcean::Servers
|
||||
end
|
||||
|
||||
tests('should have Fog::Compute::DigitalOcean::Servers inside') do
|
||||
servers.each do |s|
|
||||
test { s.kind_of? Fog::Compute::DigitalOcean::Server }
|
||||
end
|
||||
end
|
||||
|
||||
tests('should be able to reload itself').succeeds { servers.reload }
|
||||
|
||||
tests('should be able to get a model') do
|
||||
test('by instance id') do
|
||||
servers.get(server.id).kind_of? Fog::Compute::DigitalOcean::Server
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
Shindo.tests("Fog::Compute[:digitalocean] | ssh_key model", ['digitalocean', 'compute']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
|
||||
tests('The ssh_key model should') do
|
||||
|
||||
test('#save') do
|
||||
@key = service.ssh_keys.create :name => 'fookey',
|
||||
:ssh_pub_key => 'fookey'
|
||||
@key.is_a? Fog::Compute::DigitalOcean::SshKey
|
||||
end
|
||||
tests('have the action') do
|
||||
test('reload') { @key.respond_to? 'reload' }
|
||||
%w{
|
||||
save
|
||||
destroy
|
||||
}.each do |action|
|
||||
test(action) { @key.respond_to? action }
|
||||
end
|
||||
end
|
||||
tests('have attributes') do
|
||||
attributes = [
|
||||
:id,
|
||||
:name,
|
||||
:ssh_pub_key
|
||||
]
|
||||
tests("The key model should respond to") do
|
||||
attributes.each do |attribute|
|
||||
test("#{attribute}") { @key.respond_to? attribute }
|
||||
end
|
||||
end
|
||||
end
|
||||
test('#destroy') do
|
||||
@key.destroy
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | ssh_keys collection', ['digitalocean']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
|
||||
tests('The ssh_keys collection') do
|
||||
key = service.ssh_keys.create :name => 'fookey',
|
||||
:ssh_pub_key => 'fookey'
|
||||
[:all, :get].each do |method|
|
||||
test("should respond to #{method}") do
|
||||
service.ssh_keys.respond_to? method
|
||||
end
|
||||
end
|
||||
|
||||
tests('should have Fog::Compute::DigitalOcean::SshKey inside') do
|
||||
service.ssh_keys.each do |s|
|
||||
test { s.kind_of? Fog::Compute::DigitalOcean::SshKey }
|
||||
end
|
||||
end
|
||||
|
||||
tests('should be able to get a model') do
|
||||
test('by instance id') do
|
||||
service.ssh_keys.get(key.id).kind_of? Fog::Compute::DigitalOcean::SshKey
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | create_server request', ['digitalocean', 'compute']) do
|
||||
|
||||
@server_format = {
|
||||
'id' => Integer,
|
||||
'name' => String,
|
||||
'image_id' => Integer,
|
||||
'size_id' => Integer,
|
||||
'event_id' => Integer
|
||||
}
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#create_server').formats({'status' => 'OK', 'droplet' => @server_format}) do
|
||||
image = service.images.find { |img| img.name == 'Ubuntu 12.04 x64 Server' }
|
||||
flavor = service.flavors.find { |f| f.name == '512MB' }
|
||||
data = Fog::Compute[:digitalocean].create_server 'fog-test-server',
|
||||
flavor.id,
|
||||
image.id,
|
||||
service.regions.first.id
|
||||
data.body
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | create_ssh_key request', ['digitalocean', 'compute']) do
|
||||
|
||||
@key_format = {
|
||||
'id' => Integer,
|
||||
'name' => String,
|
||||
'ssh_pub_key' => String
|
||||
}
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#create_ssh_key').formats({'status' => 'OK', 'ssh_key' => @key_format}) do
|
||||
@key = Fog::Compute[:digitalocean].create_ssh_key 'fookey', 'fookey'
|
||||
@key.body
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
service.destroy_ssh_key @key.body['ssh_key']['id']
|
||||
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | destroy_server request', ['digitalocean', 'compute']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
server = fog_test_server
|
||||
|
||||
tests('success') do
|
||||
|
||||
test('#destroy_server') do
|
||||
service.destroy_server(server.id).body['status'] == 'OK'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | destroy_ssh_key request', ['digitalocean', 'compute']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
|
||||
tests('success') do
|
||||
|
||||
test('#destroy_ssh_key') do
|
||||
key = service.create_ssh_key 'fookey', 'fookey'
|
||||
service.destroy_ssh_key(key.body['ssh_key']['id']).body['status'] == 'OK'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
tests('failures') do
|
||||
test 'delete invalid key' do
|
||||
# DigitalOcean API returns 500 with this sometimes
|
||||
# so mark it as pending in real mode
|
||||
pending unless Fog.mocking?
|
||||
service.destroy_ssh_key('00000000000').body['status'] == 'ERROR'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | get_server_details request', ['digitalocean', 'compute']) do
|
||||
|
||||
tests('success') do
|
||||
|
||||
test('#get_server_details') do
|
||||
server = fog_test_server
|
||||
body = Fog::Compute[:digitalocean].get_server_details(server.id).body
|
||||
body['droplet']['name'] == 'fog-test-server'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | get_ssh_keys request', ['digitalocean', 'compute']) do
|
||||
|
||||
@ssh_key_format = {
|
||||
'id' => Integer,
|
||||
'name' => String,
|
||||
'ssh_pub_key' => String,
|
||||
}
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#get_ssh_key') do
|
||||
key = service.create_ssh_key 'fookey', 'ssh-dss FOO'
|
||||
tests('format').data_matches_schema(@ssh_key_format) do
|
||||
service.get_ssh_key(key.body['ssh_key']['id']).body['ssh_key']
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | list_flavors request', ['digitalocean', 'compute']) do
|
||||
|
||||
# {"id":2,"name":"Amsterdam 1"}
|
||||
@flavor_format = {
|
||||
'id' => Integer,
|
||||
'name' => String,
|
||||
}
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#list_flavor') do
|
||||
flavors = Fog::Compute[:digitalocean].list_flavors.body
|
||||
test 'returns a Hash' do
|
||||
flavors.is_a? Hash
|
||||
end
|
||||
tests('flavor').formats(@flavor_format, false) do
|
||||
flavors['sizes'].first
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | list_images request', ['digitalocean', 'compute']) do
|
||||
|
||||
# {"id"=>1601, "name"=>"CentOS 5.8 x64", "distribution"=>"CentOS"}
|
||||
@image_format = {
|
||||
'id' => Integer,
|
||||
'name' => String,
|
||||
'distribution' => String
|
||||
}
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#list_images') do
|
||||
images = Fog::Compute[:digitalocean].list_images.body
|
||||
test 'returns a Hash' do
|
||||
images.is_a? Hash
|
||||
end
|
||||
tests('image').formats(@image_format, false) do
|
||||
images['images'].first
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | list_regions request', ['digitalocean', 'compute']) do
|
||||
|
||||
# {"id":2,"name":"Amsterdam 1"}
|
||||
@region_format = {
|
||||
'id' => Integer,
|
||||
'name' => String,
|
||||
}
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#list_regions') do
|
||||
regions = Fog::Compute[:digitalocean].list_regions.body
|
||||
test 'returns a Hash' do
|
||||
regions.is_a? Hash
|
||||
end
|
||||
tests('region').formats(@region_format, false) do
|
||||
regions['regions'].first
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | list_servers request', ['digitalocean', 'compute']) do
|
||||
|
||||
@server_format = {
|
||||
'id' => Integer,
|
||||
'name' => String,
|
||||
'image_id' => Integer,
|
||||
'size_id' => Integer,
|
||||
'region_id' => Integer,
|
||||
'backups_active' => Fog::Nullable::Boolean,
|
||||
'ip_address' => Fog::Nullable::String,
|
||||
'status' => String
|
||||
}
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#list_servers') do
|
||||
Fog::Compute[:digitalocean].list_servers.body['droplets'].each do |server|
|
||||
tests('format').data_matches_schema(@server_format) do
|
||||
server
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | list_ssh_keys request', ['digitalocean', 'compute']) do
|
||||
|
||||
@ssh_key_format = {
|
||||
'id' => Integer,
|
||||
'name' => String
|
||||
}
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#list_ssh_keys') do
|
||||
Fog::Compute[:digitalocean].create_ssh_key 'fookey', 'ssh-dss FOO'
|
||||
Fog::Compute[:digitalocean].list_ssh_keys.body['ssh_keys'].each do |key|
|
||||
tests('format').data_matches_schema(@ssh_key_format) do
|
||||
key
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | power_cycle_server request', ['digitalocean', 'compute']) do
|
||||
|
||||
server = fog_test_server
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#power_cycle_server') do
|
||||
test('returns 200') do
|
||||
service.power_cycle_server(server.id).status == 200
|
||||
end
|
||||
test('state is off') do
|
||||
server.wait_for { server.state == 'off' }
|
||||
server.state == 'off'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | power on/off/shutdown requests',
|
||||
['digitalocean', 'compute']) do
|
||||
|
||||
service = Fog::Compute[:digitalocean]
|
||||
server = fog_test_server
|
||||
|
||||
tests('success') do
|
||||
|
||||
test('#power_off_server') do
|
||||
service.power_off_server(server.id).body['status'] == 'OK'
|
||||
end
|
||||
|
||||
test('#power_on_server') do
|
||||
service.power_on_server(server.id).body['status'] == 'OK'
|
||||
end
|
||||
|
||||
test('#shutdown_server') do
|
||||
service.shutdown_server(server.id).body['status'] == 'OK'
|
||||
end
|
||||
|
||||
server.start
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
Shindo.tests('Fog::Compute[:digitalocean] | reboot_server request', ['digitalocean', 'compute']) do
|
||||
|
||||
server = fog_test_server
|
||||
|
||||
tests('success') do
|
||||
|
||||
tests('#reboot_server').succeeds do
|
||||
service.reboot_server(server.id).body['status'] == 'OK'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
Загрузка…
Ссылка в новой задаче