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

Merge branch 'master' of github.com:geemus/fog

This commit is contained in:
geemus 2011-08-03 09:42:00 -05:00
commit 63c6f35668
77 changed files with 2151 additions and 43 deletions

View file

@ -5,6 +5,10 @@ title: Press
Mentions and blog posts from elsewhere in reverse chronological order by day (and alphasorted for same days).
**August 1st, 2011**
* [Using EBS Snapshots with Fog](http://www.mediamolecule.com/lab/article/using_ebs_snapshots_with_fog/)
**June 21st, 2011**
* [Mocking fog When Using It With Carrierwave](http://www.engineyard.com/blog/2011/mocking-fog-when-using-it-with-carrierwave/)

View file

@ -25,27 +25,24 @@ module Fog
attribute :preferred_backup_window, :aliases => 'PreferredBackupWindow'
attribute :preferred_maintenance_window, :aliases => 'PreferredMaintenanceWindow'
attribute :db_name, :aliases => 'DBName'
attribute :db_security_groups, :aliases => 'DBSecurityGroups'
attribute :db_security_groups, :aliases => 'DBSecurityGroups', :type => :array
attribute :db_parameter_groups, :aliases => 'DBParameterGroups'
attribute :backup_retention_period, :aliases => 'BackupRetentionPeriod', :type => :integer
attribute :license_model, :aliases => 'LicenseModel'
attr_accessor :password, :parameter_group_name, :security_group_names, :port
def initialize(attributes={})
self.flavor_id ||= 'db.m1.small'
super
end
def create_read_replica(replica_id, options={})
connection.create_db_instance_read_replica(replica_id, id, options)
options[:security_group_names] ||= options['DBSecurityGroups']
params = self.class.new(options).attributes_to_params
connection.create_db_instance_read_replica(replica_id, id, params)
connection.servers.get(replica_id)
end
def ready?
state == 'available'
end
def destroy(snapshot_identifier=nil)
requires :id
connection.delete_db_instance(id, snapshot_identifier, snapshot_identifier.nil?)
@ -56,51 +53,58 @@ module Fog
connection.reboot_db_instance(id)
true
end
def snapshots
requires :id
connection.snapshots(:server => self)
end
def modify(immediately, options)
data = connection.modify_db_instance(id, immediately, options)
options[:security_group_names] ||= options['DBSecurityGroups']
params = self.class.new(options).attributes_to_params
data = connection.modify_db_instance(id, immediately, params)
merge_attributes(data.body['ModifyDBInstanceResult']['DBInstance'])
true
true
end
def save
requires :engine
requires :allocated_storage
requires :master_username
requires :password
self.flavor_id ||= 'db.m1.small'
data = connection.create_db_instance(id, attributes_to_params)
merge_attributes(data.body['CreateDBInstanceResult']['DBInstance'])
true
end
# Converts attributes to a parameter hash suitable for requests
def attributes_to_params
options = {
'AllocatedStorage' => allocated_storage,
'AutoMinorVersionUpgrade' => auto_minor_version_upgrade,
'BackupRetentionPeriod' => backup_retention_period,
'DBName' => db_name,
'DBParameterGroupName' => parameter_group_name,
'DBParameterGroupName' => parameter_group_name || attributes['DBParameterGroupName'],
'DBSecurityGroups' => security_group_names,
'DBInstanceIdentifier' => id,
'AvailabilityZone' => availability_zone,
'DBInstanceClass' => flavor_id,
'Port' => port,
'Port' => port || attributes['Port'],
'Engine' => engine,
'EngineVersion' => engine_version,
'MasterUsername' => master_username,
'MasterUserPassword' => password,
'MasterUserPassword' => password || attributes['MasterUserPassword'],
'PreferredMaintenanceWindow' => preferred_maintenance_window,
'PreferredBackupWindow' => preferred_backup_window,
'MultiAZ' => multi_az,
'LicenseModel' => license_model
}
options.delete_if {|key, value| value.nil?}
data = connection.create_db_instance(id, options)
merge_attributes(data.body['CreateDBInstanceResult']['DBInstance'])
true
end
end
end
end

View file

@ -9,6 +9,8 @@ class Rackspace < Fog::Bin
Fog::Compute::Rackspace
when :storage
Fog::Storage::Rackspace
when :load_balancer
Fog::Rackspace::LoadBalancer
else
raise ArgumentError, "Unrecognized service: #{key}"
end

View file

@ -8,6 +8,7 @@ module Fog
service(:cdn, 'cdn/rackspace')
service(:compute, 'compute/rackspace')
service(:storage, 'storage/rackspace')
service(:load_balancer, 'rackspace/load_balancer')
def self.authenticate(options)
rackspace_auth_url = options[:rackspace_auth_url] || "auth.api.rackspacecloud.com"

View file

@ -0,0 +1,161 @@
module Fog
module Rackspace
class LoadBalancer < Fog::Service
class ServiceError < Fog::Errors::Error
attr_reader :response_data
def self.slurp(error)
if error.response.body.empty?
data = nil
message = nil
else
data = JSON.parse(error.response.body)
message = data['message']
end
new_error = super(error, message)
new_error.instance_variable_set(:@response_data, data)
new_error
end
end
class InternalServerError < ServiceError; end
class BadRequest < ServiceError
#TODO - Need to find a bette way to print out these validation errors when they are thrown
attr_reader :validation_errors
def self.slurp(error)
new_error = super(error)
unless new_error.response_data.nil?
new_error.instance_variable_set(:@validation_errors, new_error.response_data['validationErrors'])
end
new_error
end
end
DFW_ENDPOINT = 'https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/'
ORD_ENDPOINT = 'https://ord.loadbalancers.api.rackspacecloud.com/v1.0/'
LON_ENDPOINT = 'https://lon.loadbalancers.api.rackspacecloud.com/v1.0/'
requires :rackspace_api_key, :rackspace_username
recognizes :rackspace_auth_url
recognizes :rackspace_auth_token
model_path 'fog/rackspace/models'
collection :load_balancers
model :load_balancer
collection :nodes
model :node
collection :virtual_ips
model :virtual_ip
collection :access_rules
model :access_rule
request_path 'fog/rackspace/requests'
request :create_load_balancer
request :get_load_balancer
request :list_load_balancers
request :update_load_balancer
request :delete_load_balancer
request :create_node
request :list_nodes
request :get_node
request :update_node
request :delete_node
request :delete_nodes
request :create_virtual_ip
request :list_virtual_ips
request :delete_virtual_ip
request :list_protocols
request :list_algorithms
request :get_connection_logging
request :set_connection_logging
request :create_access_rule
request :list_access_rules
request :delete_access_rule
request :delete_all_access_rules
request :get_session_persistence
request :set_session_persistence
request :remove_session_persistence
request :get_connection_throttling
request :remove_connection_throttling
request :set_connection_throttling
request :get_monitor
request :set_monitor
request :remove_monitor
request :get_usage
request :get_load_balancer_usage
class Real
def initialize(options={})
require 'json'
@rackspace_api_key = options[:rackspace_api_key]
@rackspace_username = options[:rackspace_username]
@rackspace_auth_url = options[:rackspace_auth_url]
@rackspace_must_reauthenticate = false
uri = URI.parse(options[:rackspace_lb_endpoint] || DFW_ENDPOINT)
@host = uri.host
@path = uri.path
@port = uri.port
@scheme = uri.scheme
authenticate
@connection = Fog::Connection.new(uri.to_s, options[:persistent])
end
def protocols
list_protocols.body['protocols']
end
def algorithms
list_algorithms.body['algorithms'].collect { |i| i['name'] }
end
def request(params)
#TODO - Unify code with other rackspace services
begin
response = @connection.request(params.merge!({
:headers => {
'Content-Type' => 'application/json',
'X-Auth-Token' => @auth_token
}.merge!(params[:headers] || {}),
:host => @host,
:path => "#{@path}/#{params[:path]}"
}))
rescue Excon::Errors::NotFound => error
raise NotFound.slurp error
rescue Excon::Errors::BadRequest => error
raise BadRequest.slurp error
rescue Excon::Errors::InternalServerError => error
raise InternalServerError.slurp error
rescue Excon::Errors::HTTPStatusError => error
raise ServiceError.slurp error
end
unless response.body.empty?
response.body = JSON.parse(response.body)
end
response
end
def authenticate
options = {
:rackspace_api_key => @rackspace_api_key,
:rackspace_username => @rackspace_username,
:rackspace_auth_url => @rackspace_auth_url
}
credentials = Fog::Rackspace.authenticate(options)
@auth_token = credentials['X-Auth-Token']
account_id = credentials['X-Server-Management-Url'].match(/.*\/([\d]+)$/)[1]
@path = "#{@path}/#{account_id}"
end
def usage(options = {})
get_usage(options).body
end
end
end
end
end

View file

@ -0,0 +1,39 @@
require 'fog/core/model'
module Fog
module Rackspace
class LoadBalancer
class AccessRule < Fog::Model
identity :id
attribute :address
attribute :type
def destroy
requires :identity, :load_balancer
connection.delete_access_rule(load_balancer.identity, identity)
true
end
def save
raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if identity
requires :load_balancer, :address, :type
connection.create_access_rule(load_balancer.id, address, type)
#Unfortunately, access rules creation doesn't return an ID, we require a subsequent list call and comparison
data = connection.list_access_rules(load_balancer.id).body['accessList']
.select { |ar| ar['address'] == address and ar['type'] == type }
.first
merge_attributes(data)
true
end
private
def load_balancer
collection.load_balancer
end
end
end
end
end

View file

@ -0,0 +1,29 @@
require 'fog/core/collection'
require 'fog/rackspace/models/access_rule'
module Fog
module Rackspace
class LoadBalancer
class AccessRules < Fog::Collection
model Fog::Rackspace::LoadBalancer::AccessRule
attr_accessor :load_balancer
def all
load(all_raw)
end
def get(access_rule_id)
data = all_raw.select { |access_rule| access_rule['id'] == access_rule_id }.first
data && new(data)
end
private
def all_raw
requires :load_balancer
data = connection.list_access_rules(load_balancer.id).body['accessList']
end
end
end
end
end

View file

@ -0,0 +1,216 @@
require 'fog/core/model'
module Fog
module Rackspace
class LoadBalancer
class LoadBalancer < Fog::Model
#States
ACTIVE = 'ACTIVE'
ERROR = 'ERROR'
PENDING_UPDATE = 'PENDING_UPDATE'
PENDING_DELTE = 'PENDING_DELETE'
SUSPENDED = 'SUSPENDED'
DELETED = 'DELETED'
BUILD = 'BUILD'
identity :id
attribute :cluster
attribute :connection_logging, :aliases => 'connectionLogging'
attribute :port
attribute :protocol
attribute :algorithm
attribute :virtual_ips, :aliases => 'virtualIps'
attribute :created
attribute :updated
attribute :name
attribute :state, :aliases => 'status'
attribute :nodes
def initialize(attributes)
#HACK - Since we are hacking how sub-collections work, we have to make sure the connection is valid first.
@connection = attributes[:connection]
super
end
def access_rules
@access_rules ||= begin
Fog::Rackspace::LoadBalancer::AccessRules.new({
:connection => connection,
:load_balancer => self})
end
end
def access_rules=(new_access_rules=[])
access_rules.load(new_access_rules)
end
def nodes
@nodes ||= begin
Fog::Rackspace::LoadBalancer::Nodes.new({
:connection => connection,
:load_balancer => self})
end
end
def nodes=(new_nodes=[])
nodes.load(new_nodes)
end
def virtual_ips
@virtual_ips ||= begin
Fog::Rackspace::LoadBalancer::VirtualIps.new({
:connection => connection,
:load_balancer => self})
end
end
def virtual_ips=(new_virtual_ips=[])
virtual_ips.load(new_virtual_ips)
end
def connection_logging
attributes[:connection_logging]
end
def enable_connection_logging
requires :identity
connection.set_connection_logging identity, true
attributes[:connection_logging] = true
end
def disable_connection_logging
requires :identity
connection.set_connection_logging identity, false
attributes[:connection_logging] = false
end
def health_monitor
requires :identity
monitor = connection.get_monitor(identity).body['healthMonitor']
monitor.count == 0 ? nil : monitor
end
def enable_health_monitor(type, delay, timeout, attempsBeforeDeactivation, options = {})
requires :identity
connection.set_monitor(identity, type, delay, timeout, attempsBeforeDeactivation, options = {})
true
end
def disable_health_monitor
requires :identity
connection.remove_monitor(identity)
true
end
def connection_throttling
requires :identity
throttle = connection.get_connection_throttling(identity).body['connectionThrottle']
throttle.count == 0 ? nil : throttle
end
def enable_connection_throttling(max_connections, min_connections, max_connection_rate, rate_interval)
requires :identity
connection.set_connection_throttling(identity, max_connections, min_connections, max_connection_rate, rate_interval)
true
end
def disable_connection_throttling
requires :identity
connection.remove_connection_throttling(identity)
true
end
def session_persistence
requires :identity
persistence = connection.get_session_persistence(identity).body['sessionPersistence']
persistence.count == 0 ? nil : persistence
end
def enable_session_persistence(type)
requires :identity
connection.set_session_persistence(identity, type)
true
end
def disable_session_persistence
requires :identity
connection.remove_session_persistence(identity)
true
end
def destroy
requires :identity
connection.delete_load_balancer(identity)
true
end
def ready?
state == ACTIVE
end
def save
if identity
update
else
create
end
true
end
def usage(options = {})
requires :identity
connection.get_load_balancer_usage(identity, options).body
end
private
def create
requires :name, :protocol, :port, :virtual_ips, :nodes
data = connection.create_load_balancer(name, protocol, port, virtual_ips_hash, nodes_hash)
merge_attributes(data.body['loadBalancer'])
end
def update
requires :name, :protocol, :port, :algorithm
options = {
:name => name,
:algorithm => algorithm,
:protocol => protocol,
:port => port}
connection.update_load_balancer(identity, options)
#TODO - Should this bubble down to nodes? Without tracking changes this would be very inefficient.
# For now, individual nodes will have to be saved individually after saving an LB
end
def virtual_ips_hash
virtual_ips.collect do |virtual_ip|
{ :type => virtual_ip.type }
end
end
def nodes_hash
nodes.collect do |node|
{ :address => node.address, :port => node.port, :condition => node.condition, :weight => node.weight }
end
end
def connection_logging=(new_value)
if !new_value.nil? and new_value.is_a?(Hash)
attributes[:connection_logging] = case new_value['enabled']
when 'true'
true
when 'false'
false
end
else
attributes[:connection_logging] = new_value
end
end
end
end
end
end

View file

@ -0,0 +1,27 @@
require 'fog/core/collection'
require 'fog/rackspace/models/load_balancer'
module Fog
module Rackspace
class LoadBalancer
class LoadBalancers < Fog::Collection
model Fog::Rackspace::LoadBalancer::LoadBalancer
def all
data = connection.list_load_balancers.body['loadBalancers']
load(data)
end
def get(load_balancer_id)
if load_balancer = connection.get_load_balancer(load_balancer_id).body['loadBalancer']
new(load_balancer)
end
rescue Fog::Rackspace::LoadBalancer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,58 @@
require 'fog/core/model'
module Fog
module Rackspace
class LoadBalancer
class Node < Fog::Model
identity :id
attribute :address
attribute :status
attribute :weight
attribute :port
attribute :condition
def destroy
requires :identity, :load_balancer
connection.delete_node(load_balancer.identity, identity)
true
end
def save
if identity
update
else
create
end
true
end
private
def load_balancer
collection.load_balancer
end
def create
requires :load_balancer, :address, :condition, :port
options = {}
unless weight.nil?
options[:weight] = weight
end
data = connection.create_node(load_balancer.id, address, port, condition, options)
merge_attributes(data.body['nodes'][0])
end
def update
requires :load_balancer, :identity
options = {
:condition => condition
}
unless weight.nil?
options[:weight] = weight
end
connection.update_node(load_balancer.id, identity, options)
end
end
end
end
end

View file

@ -0,0 +1,29 @@
require 'fog/core/collection'
require 'fog/rackspace/models/node'
module Fog
module Rackspace
class LoadBalancer
class Nodes < Fog::Collection
model Fog::Rackspace::LoadBalancer::Node
attr_accessor :load_balancer
def all
requires :load_balancer
data = connection.list_nodes(load_balancer.id).body['nodes']
load(data)
end
def get(node_id)
requires :load_balancer
if node = connection.get_node(load_balancer.id, node_id).body['node']
new(node)
end
rescue Fog::Rackspace::LoadBalancer::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,35 @@
require 'fog/core/model'
module Fog
module Rackspace
class LoadBalancer
class VirtualIp < Fog::Model
identity :id
attribute :address
attribute :type
attribute :ip_version, :aliases => 'ipVersion'
def destroy
requires :identity, :load_balancer
connection.delete_virtual_ip(load_balancer.identity, identity)
true
end
def save
raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if identity
requires :load_balancer, :type
data = connection.create_virtual_ip(load_balancer.id, type)
merge_attributes(data.body)
true
end
private
def load_balancer
collection.load_balancer
end
end
end
end
end

View file

@ -0,0 +1,32 @@
require 'fog/core/collection'
require 'fog/rackspace/models/virtual_ip'
module Fog
module Rackspace
class LoadBalancer
class VirtualIps < Fog::Collection
model Fog::Rackspace::LoadBalancer::VirtualIp
attr_accessor :load_balancer
def all
data = all_raw
load(data)
end
#HACK - This method is somewhat hacky since there isn't a way to retrieve a single virtual IP. Hopefully long term a method will
# be added that allows a single virtual IP to be returned
def get(virtual_ip_id)
data = all_raw.select { |virtual_ip| virtual_ip['id'] == virtual_ip_id }.first
data && new(data)
end
private
def all_raw
requires :load_balancer
connection.list_virtual_ips(load_balancer.id).body['virtualIps']
end
end
end
end
end

View file

@ -0,0 +1,24 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def create_access_rule(load_balancer_id, address, type)
#TODO - This can actually support adding multiple access rules.
data = {
'accessList' => [
{
'address' => address,
'type' => type
}
]}
request(
:body => data.to_json,
:expects => [200, 202],
:method => 'POST',
:path => "loadbalancers/#{load_balancer_id}/accesslist"
)
end
end
end
end
end

View file

@ -0,0 +1,31 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def create_load_balancer(name, protocol, port, virtual_ips, nodes)
data = {
'loadBalancer' => {
'name' => name,
'port' => port,
'protocol' => protocol,
'virtualIps' => virtual_ips,
'nodes' => nodes
#Is algorithm allowed on create?
}
}
request(
:body => data.to_json,
:expects => 202,
:method => 'POST',
:path => 'loadbalancers.json'
)
end
end
class Mock
def create_load_balancer(options = {})
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,32 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def create_node(load_balancer_id, address, port, condition, options = {})
data = {
'nodes' => [
{
'address' => address,
'port' => port,
'condition' => condition
}
]}
if options.has_key?(:weight)
data['nodes'][0]['weight'] = options[:weight]
end
request(
:body => data.to_json,
:expects => [200, 202],
:method => 'POST',
:path => "loadbalancers/#{load_balancer_id}/nodes.json"
)
end
end
class Mock
def create_node(options = {})
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,25 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def create_virtual_ip(load_balancer_id, type)
data = {
'type' => type,
'ipVersion' => 'IPV6'
}
request(
:body => data.to_json,
:expects => [200, 202],
:method => 'POST',
:path => "loadbalancers/#{load_balancer_id}/virtualips.json"
)
end
end
class Mock
def create_virtual_ip(load_balancer_id, type)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def delete_access_rule(load_balancer_id, access_rule_id)
request(
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/accesslist/#{access_rule_id}",
:method => 'DELETE'
)
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def delete_all_access_rules(load_balancer_id)
request(
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/accesslist",
:method => 'DELETE'
)
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def delete_load_balancer(load_balancer_id)
request(
:expects => 202,
:path => "loadbalancers/#{load_balancer_id}.json",
:method => 'DELETE'
)
end
end
class Mock
def delete_load_balancer(load_balancer_id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def delete_node(load_balancer_id, node_id)
request(
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/nodes/#{node_id}",
:method => 'DELETE'
)
end
end
class Mock
def delete_node(load_balancer_id, node_id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,22 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def delete_nodes(load_balancer_id, *node_ids)
query_string = node_ids.collect { |node_id| "id=#{node_id}" }.join('&')
puts query_string
request(
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/nodes?#{node_ids}",
:method => 'DELETE'
)
end
end
class Mock
def delete_nodes(load_balancer_id, *node_ids)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def delete_virtual_ip(load_balancer_id, virtual_ip_id)
request(
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/virtualips/#{virtual_ip_id}",
:method => 'DELETE'
)
end
end
class Mock
def delete_virtual_ip(load_balancer_id, virtual_ip_id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def get_connection_logging(load_balancer_id)
request(
:expects => 200,
:path => "loadbalancers/#{load_balancer_id}/connectionlogging",
:method => 'GET'
)
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def get_connection_throttling(load_balancer_id)
request(
:expects => 200,
:path => "loadbalancers/#{load_balancer_id}/connectionthrottle",
:method => 'GET'
)
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def get_load_balancer(load_balancer_id)
request(
:expects => 200,
:path => "loadbalancers/#{load_balancer_id}.json",
:method => 'GET'
)
end
end
class Mock
def get_load_balancer(options = {})
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,21 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def get_load_balancer_usage(load_balancer_id, options = {})
#TODO - Didn't implement usage/current. Not sure if it is needed
if options.has_key? :start_time and options.has_key? :end_time
query = "?startTime=#{options[:start_time]}&endTime=#{options[:end_time]}"
else
query = ''
end
request(
:expects => 200,
:path => "loadbalancers/#{load_balancer_id}/usage#{query}",
:method => 'GET'
)
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def get_monitor(load_balancer_id)
request(
:expects => 200,
:path => "loadbalancers/#{load_balancer_id}/healthmonitor",
:method => 'GET'
)
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def get_node(load_balancer_id, node_id)
request(
:expects => 200,
:path => "loadbalancers/#{load_balancer_id}/nodes/#{node_id}.json",
:method => 'GET'
)
end
end
class Mock
def get_node(options = {})
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def get_session_persistence(load_balancer_id)
request(
:expects => 200,
:path => "loadbalancers/#{load_balancer_id}/sessionpersistence",
:method => 'GET'
)
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def get_usage(options = {})
if options.has_key? :start_time and options.has_key? :end_time
query = "?startTime=#{options[:start_time]}&endTime=#{options[:end_time]}"
else
query = ''
end
request(
:expects => 200,
:path => "loadbalancers/usage#{query}",
:method => 'GET'
)
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def list_access_rules(load_balancer_id)
request(
:expects => 200,
:method => 'GET',
:path => "loadbalancers/#{load_balancer_id}/accesslist"
)
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def list_algorithms
request(
:expects => 200,
:method => 'GET',
:path => 'loadbalancers/algorithms'
)
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def list_load_balancers
request(
:expects => 200,
:method => 'GET',
:path => 'loadbalancers.json'
)
end
end
class Mock
def list_load_balancers
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def list_nodes(load_balancer_id)
request(
:expects => 200,
:method => 'GET',
:path => "loadbalancers/#{load_balancer_id}/nodes.json"
)
end
end
class Mock
def list_nodes(load_balancer_id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def list_protocols
request(
:expects => 200,
:method => 'GET',
:path => 'loadbalancers/protocols'
)
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def list_virtual_ips(load_balancer_id)
request(
:expects => 200,
:method => 'GET',
:path => "loadbalancers/#{load_balancer_id}/virtualips.json"
)
end
end
class Mock
def list_virtual_ips(load_balancer_id)
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def remove_connection_throttling(load_balancer_id)
request(
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/connectionthrottle",
:method => 'DELETE'
)
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def remove_monitor(load_balancer_id)
request(
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/healthmonitor",
:method => 'DELETE'
)
end
end
end
end
end

View file

@ -0,0 +1,15 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def remove_session_persistence(load_balancer_id)
request(
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/sessionpersistence",
:method => 'DELETE'
)
end
end
end
end
end

View file

@ -0,0 +1,21 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def set_connection_logging(load_balancer_id, value)
data = {
'connectionLogging' => {
'enabled' => value.to_s
}
}
request(
:body => data.to_json,
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/connectionlogging",
:method => 'PUT'
)
end
end
end
end
end

View file

@ -0,0 +1,22 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def set_connection_throttling(load_balancer_id, max_connections, min_connections, max_connection_rate, rate_interval)
data = {
'maxConnections' => max_connections,
'minConnections' => min_connections,
'maxConnectionRate' => max_connection_rate,
'rateInterval' => rate_interval
}
request(
:body => data.to_json,
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/connectionthrottle",
:method => 'PUT'
)
end
end
end
end
end

View file

@ -0,0 +1,31 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def set_monitor(load_balancer_id, type, delay, timeout, attempsBeforeDeactivation, options = {})
data = {
'type' => type,
'delay' => delay,
'timeout' => timeout,
'attemptsBeforeDeactivation' => attempsBeforeDeactivation
}
if options.has_key? :path
data['path'] = options[:path]
end
if options.has_key? :body_regex
data['bodyRegex'] = options[:body_regex]
end
if options.has_key? :status_regex
data['statusRegex'] = options[:status_regex]
end
request(
:body => data.to_json,
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/healthmonitor",
:method => 'PUT'
)
end
end
end
end
end

View file

@ -0,0 +1,21 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def set_session_persistence(load_balancer_id, persistence_type)
data = {
'sessionPersistence' => {
'persistenceType' => persistence_type
}
}
request(
:body => data.to_json,
:expects => [200, 202],
:path => "loadbalancers/#{load_balancer_id}/sessionpersistence",
:method => 'PUT'
)
end
end
end
end
end

View file

@ -0,0 +1,29 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def update_load_balancer(load_balancer_id, options = {})
data = {
'loadBalancer' => {
'name' => options[:name],
'port' => options[:port],
'protocol' => options[:protocol],
'algorithm' => options[:algorithm]
}
}
request(
:body => data.to_json,
:expects => 202,
:method => 'PUT',
:path => "loadbalancers/#{load_balancer_id}.json"
)
end
end
class Mock
def update_load_balancer(options = {})
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -0,0 +1,31 @@
module Fog
module Rackspace
class LoadBalancer
class Real
def update_node(load_balancer_id, node_id, options = {})
data = {
'node' => {}
}
if options.has_key? :weight
data['node']['weight'] = options[:weight]
end
if options.has_key? :condition
data['node']['condition'] = options[:condition]
end
#TODO - Do anything if no valid options are passed in?
request(
:body => data.to_json,
:expects => [200, 202],
:method => 'PUT',
:path => "loadbalancers/#{load_balancer_id}/nodes/#{node_id}.json"
)
end
end
class Mock
def update_node(options = {})
Fog::Mock.not_implemented
end
end
end
end
end

View file

@ -179,6 +179,7 @@ module Fog
def initialize(options={})
require 'mime/types'
require 'multi_json'
@aws_access_key_id = options[:aws_access_key_id]
@aws_secret_access_key = options[:aws_secret_access_key]
options[:region] ||= 'us-east-1'

View file

@ -30,7 +30,7 @@ module Fog
# http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectCOPY.html
def copy_object(source_bucket_name, source_object_name, target_bucket_name, target_object_name, options = {})
headers = { 'x-amz-copy-source' => "/#{source_bucket_name}/#{source_object_name}" }.merge!(options)
headers = { 'x-amz-copy-source' => "/#{source_bucket_name}/#{CGI.escape(source_object_name)}" }.merge!(options)
request({
:expects => 200,
:headers => headers,

View file

@ -60,17 +60,18 @@ module Fog
class Mock # :nodoc:all
def get_bucket(bucket_name, options = {})
prefix, marker, delimiter, max_keys = \
options['prefix'], options['marker'], options['delimiter'], options['max-keys']
unless bucket_name
raise ArgumentError.new('bucket_name is required')
end
if options['delimiter']
Fog::Mock.not_implemented
end
response = Excon::Response.new
if bucket = self.data[:buckets][bucket_name]
contents = bucket[:objects].values.sort {|x,y| x['Key'] <=> y['Key']}.reject do |object|
(options['prefix'] && object['Key'][0...options['prefix'].length] != options['prefix']) ||
(options['marker'] && object['Key'] <= options['marker'])
(prefix && object['Key'][0...prefix.length] != prefix) ||
(marker && object['Key'] <= marker) ||
(delimiter && object['Key'][(prefix ? prefix.length : 0)..-1].include?(delimiter))
end.map do |object|
data = object.reject {|key, value| !['ETag', 'Key', 'StorageClass'].include?(key)}
data.merge!({
@ -80,7 +81,7 @@ module Fog
})
data
end
max_keys = options['max-keys'] || 1000
max_keys = max_keys || 1000
size = [max_keys, 1000].min
truncated_contents = contents[0...size]
@ -89,14 +90,14 @@ module Fog
'CommonPrefixes' => [],
'Contents' => truncated_contents,
'IsTruncated' => truncated_contents.size != contents.size,
'Marker' => options['marker'],
'Marker' => marker,
'MaxKeys' => max_keys,
'Name' => bucket['Name'],
'Prefix' => options['prefix']
'Prefix' => prefix
}
if options['max-keys'] && options['max-keys'] < response.body['Contents'].length
if max_keys && max_keys < response.body['Contents'].length
response.body['IsTruncated'] = true
response.body['Contents'] = response.body['Contents'][0...options['max-keys']]
response.body['Contents'] = response.body['Contents'][0...max_keys]
end
else
response.status = 404

View file

@ -27,11 +27,9 @@ module Fog
def post_object_hidden_fields(options = {})
if options['policy']
options['policy'] = MultiJson.encode(options['policy'])
options['policy'] = Base64.encode64(MultiJson.encode(options['policy'])).gsub("\n", "")
options['AWSAccessKeyId'] = @aws_access_key_id
string_to_sign = Base64.encode64(options['policy']).chomp!
signed_string = @hmac.sign(string_to_sign)
options['Signature'] = Base64.encode64(signed_string).chomp!
options['Signature'] = Base64.encode64(@hmac.sign(options['policy'])).gsub("\n", "")
end
options
end

View file

@ -6,7 +6,7 @@ Shindo.tests("AWS::RDS | server", ['aws', 'rds']) do
# We'll need this later; create it early to avoid waiting
@instance_with_final_snapshot = AWS[:rds].servers.create(rds_default_server_params.merge(:id => uniq_id("fog-snapshot-test"), :backup_retention_period => 1))
@instance.wait_for { ready? }
@instance.wait_for(20*60) { ready? }
tests('#snapshots') do
snapshot = nil
@ -51,10 +51,10 @@ Shindo.tests("AWS::RDS | server", ['aws', 'rds']) do
@instance.reload.wait_for { state == 'rebooting' }
@instance.reload.wait_for { ready? }
# Restore back to original state
# Restore back to original state using symbols
restore_options = {
'DBParameterGroupName' => orig_parameter_group,
'DBSecurityGroups' => orig_security_groups
:parameter_group_name => orig_parameter_group,
:security_group_names => orig_security_groups
}
@instance.modify(true, restore_options)

View file

@ -103,6 +103,7 @@ class Brightbox
"url" => String,
"id" => String,
"ipv4_address" => String,
"ipv6_address" => Fog::Nullable::String,
"mac_address" => String
}
@ -281,6 +282,7 @@ class Brightbox
"verified_telephone" => Fog::Nullable::String,
"verified_at" => Fog::Nullable::String,
"verified_ip" => Fog::Nullable::String,
"valid_credit_card" => Fog::Boolean,
"owner" => Brightbox::Compute::Formats::Nested::USER,
"users" => [Brightbox::Compute::Formats::Nested::USER],
"clients" => [Brightbox::Compute::Formats::Nested::API_CLIENT],
@ -338,6 +340,7 @@ class Brightbox
"url" => String,
"id" => String,
"ipv4_address" => String,
"ipv6_address" => Fog::Nullable::String,
"mac_address" => String,
"server" => Brightbox::Compute::Formats::Nested::SERVER
}

View file

@ -55,7 +55,7 @@ Shindo.tests('Fog::Compute[:brightbox] | load balancer requests', ['brightbox'])
tests('failure') do
tests("#create_load_balancer").raises(Excon::Errors::BadRequest) do
tests("#create_load_balancer").raises(Excon::Errors::UnprocessableEntity) do
pending if Fog.mocking?
Fog::Compute[:brightbox].create_load_balancer
end

View file

@ -8,6 +8,7 @@ module Fog
module Integer; end
module String; end
module Time; end
module Float; end
end
end
[FalseClass, TrueClass].each {|klass| klass.send(:include, Fog::Boolean)}
@ -15,6 +16,7 @@ end
[NilClass, String].each {|klass| klass.send(:include, Fog::Nullable::String)}
[NilClass, Time].each {|klass| klass.send(:include, Fog::Nullable::Time)}
[Integer, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Integer)}
[Float, NilClass].each {|klass| klass.send(:include, Fog::Nullable::Float)}
module Shindo
class Tests

24
tests/rackspace/helper.rb Normal file
View file

@ -0,0 +1,24 @@
module Shindo
class Tests
def given_a_load_balancer_service(&block)
@service = Fog::Rackspace::LoadBalancer.new
instance_eval(&block)
end
def given_a_load_balancer(&block)
@lb = @service.load_balancers.create({
:name => ('fog' + Time.now.to_i.to_s),
:protocol => 'HTTP',
:port => 80,
:virtual_ips => [{ :type => 'PUBLIC'}],
:nodes => [{ :address => '10.0.0.1', :port => 80, :condition => 'ENABLED'}]
})
@lb.wait_for { ready? }
begin
instance_eval(&block)
ensure
@lb.wait_for { ready? }
@lb.destroy
end
end
end
end

View file

@ -0,0 +1,19 @@
Shindo.tests('Fog::Rackspace::LoadBalancer', ['rackspace']) do
@service = Fog::Rackspace::LoadBalancer.new
tests('#algorithms').succeeds do
data = @service.algorithms
returns(true) { data.is_a? Array }
returns(true) { data.first.is_a? String }
end
tests('#protocols').succeeds do
data = @service.protocols
returns(true) { data.is_a? Array }
end
tests('#usage').succeeds do
@service.usage
end
end

View file

@ -0,0 +1,10 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | access_list', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
model_tests(@lb.access_rules, { :address => '10.0.0.2', :type => 'ALLOW'}, false) do
@lb.wait_for { ready? }
end
end
end
end

View file

@ -0,0 +1,10 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | access_lists', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
collection_tests(@lb.access_rules, { :address => '10.0.0.2', :type => 'ALLOW'}, false) do
@lb.wait_for { ready? }
end
end
end
end

View file

@ -0,0 +1,114 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | load_balancer', ['rackspace']) do
LOAD_BALANCER_ATTRIBUTES = {
:name => 'fog' + Time.now.to_i.to_s,
:protocol => 'HTTP',
:port => 80,
:virtual_ips => [{ :type => 'PUBLIC'}],
:nodes => [{ :address => '10.0.0.1', :port => 80, :condition => 'ENABLED'}]
}
given_a_load_balancer_service do
model_tests(@service.load_balancers, LOAD_BALANCER_ATTRIBUTES, false) do
@instance.wait_for { ready? }
tests('#save => saving existing with port = 88').succeeds do
@instance.port = 88
@instance.save
end
@instance.wait_for { ready? }
tests('#enable_connection_logging').succeeds do
@instance.enable_connection_logging
returns(true) { @instance.connection_logging }
end
@instance.wait_for { ready? }
tests('#disable_connection_logging').succeeds do
@instance.disable_connection_logging
returns(false) { @instance.connection_logging }
end
tests('#usage').succeeds do
@instance.usage
end
tests("#usage(:start_time => '2010-05-10', :end_time => '2010-05-11')").succeeds do
@instance.usage(:start_time => '2010-05-10', :end_time => '2010-05-11')
end
tests("#health_monitor").returns(nil) do
@instance.health_monitor
end
@instance.wait_for { ready? }
tests("#enable_health_monitor('CONNECT', 5, 5, 5)").succeeds do
@instance.enable_health_monitor('CONNECT', 5, 5, 5)
end
@instance.wait_for { ready? }
tests("#health_monitor").succeeds do
monitor = @instance.health_monitor
returns('CONNECT') { monitor['type'] }
end
@instance.wait_for { ready? }
tests("#disable_health_monitor").succeeds do
@instance.disable_health_monitor
end
@instance.wait_for { ready? }
tests("#connection_throttling").returns(nil) do
@instance.connection_throttling
end
tests("#enable_connection_throttling(5, 5, 5, 5)").succeeds do
@instance.enable_connection_throttling(5, 5, 5, 5)
end
@instance.wait_for { ready? }
tests("#connection_throttling").succeeds do
throttle = @instance.connection_throttling
returns(5) { throttle['maxConnections'] }
end
@instance.wait_for { ready? }
tests("#disable_connection_throttling").succeeds do
@instance.disable_connection_throttling
end
@instance.wait_for { ready? }
tests("#session_persistence").returns(nil) do
@instance.session_persistence
end
tests("#enable_session_persistence('HTTP_COOKIE')").succeeds do
@instance.enable_session_persistence('HTTP_COOKIE')
end
@instance.wait_for { ready? }
tests("#connction_throttling").succeeds do
persistence = @instance.session_persistence
returns('HTTP_COOKIE') { persistence['persistenceType'] }
end
@instance.wait_for { ready? }
tests("#disable_session_persistence").succeeds do
@instance.disable_session_persistence
end
@instance.wait_for { ready? }
end
tests('failure') do
@lb = @service.load_balancers.new LOAD_BALANCER_ATTRIBUTES
tests('#usage => Requires ID').raises(ArgumentError) do
@lb.usage
end
tests('#health_monitor => Requires ID').raises(ArgumentError) do
@lb.health_monitor
end
end
end
end

View file

@ -0,0 +1,17 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | load_balancers', ['rackspace']) do
given_a_load_balancer_service do
@lb_name = 'fog' + Time.now.to_i.to_s
collection_tests(@service.load_balancers,
{
:name => @lb_name,
:protocol => 'HTTP',
:port => 80,
:virtual_ips => [{ :type => 'PUBLIC'}],
:nodes => [{ :address => '10.0.0.1', :port => 80, :condition => 'ENABLED'}]
},
false) do
@instance.wait_for { ready? }
end
end
end

View file

@ -0,0 +1,17 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | node', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
model_tests(@lb.nodes, { :address => '10.0.0.2', :port => 80, :condition => 'ENABLED'}, false) do
@lb.wait_for { ready? }
tests("#save() => existing node with port = 88").succeeds do
@instance.port = 88
@instance.save
end
@lb.wait_for { ready? }
end
end
end
end

View file

@ -0,0 +1,10 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | nodes', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
collection_tests(@lb.nodes, { :address => '10.0.0.2', :port => 80, :condition => 'ENABLED'}, false) do
@lb.wait_for { ready? }
end
end
end
end

View file

@ -0,0 +1,14 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | virtual_ip', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
model_tests(@lb.virtual_ips, { :type => 'PUBLIC'}, false) do
@lb.wait_for { ready? }
tests("#save => existing virtual IP").raises(Fog::Errors::Error) do
@instance.save
end
end
end
end
end

View file

@ -0,0 +1,10 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | virtual_ips', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
collection_tests(@lb.virtual_ips, { :type => 'PUBLIC'}, false) do
@lb.wait_for { ready? }
end
end
end
end

View file

@ -0,0 +1,54 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | access_lists_tests', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
tests('success') do
@lb.wait_for { ready? }
tests("#create_access_rule(#{@lb.id}, '67.0.0.1','ALLOW')").succeeds do
@service.create_access_rule(@lb.id, '67.0.0.1', 'ALLOW').body
end
@lb.wait_for { ready? }
tests("list_access_rules").formats(ACCESS_LIST_FORMAT) do
data = @service.list_access_rules(@lb.id).body
returns(1) { data.size }
@access_list_id = data['accessList'].first['id']
data
end
@lb.wait_for {ready? }
tests("delete_access_rule(#{@lb.id}, #{@access_list_id}").succeeds do
@service.delete_access_rule(@lb.id, @access_list_id)
end
@lb.wait_for {ready? }
tests("delete_all_access_rules(#{@lb.id})").succeeds do
#This could be refactored once we can add multiple access rules at once
@service.create_access_rule(@lb.id, '67.0.0.2', 'ALLOW')
@lb.wait_for {ready? }
@service.create_access_rule(@lb.id, '67.0.0.3', 'ALLOW')
@lb.wait_for {ready? }
returns(2) { @service.list_access_rules(@lb.id).body['accessList'].size }
@service.delete_all_access_rules(@lb.id)
@lb.wait_for {ready? }
returns(0) { @service.list_access_rules(@lb.id).body['accessList'].size }
end
end
tests('failure') do
tests('create_access_rule(invalid ip)').raises(Fog::Rackspace::LoadBalancer::BadRequest) do
@service.create_access_rule(@lb.id, '', 'ALLOW')
end
tests('create_access_rule(invalid type)').raises(Fog::Rackspace::LoadBalancer::BadRequest) do
@service.create_access_rule(@lb.id, '10.10.10.10', 'ENABLED')
end
tests("delete_access_rule(#{@lb.id}, 0)").raises(Fog::Rackspace::LoadBalancer::NotFound) do
@service.delete_access_rule(@lb.id, 0)
end
end
end
end
end

View file

@ -0,0 +1,17 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | algorithm_tests', ['rackspace']) do
ALGORITHMS_FORMAT = {
'algorithms' => [
{
'name' => String
}
]}
@service = Fog::Rackspace::LoadBalancer.new
tests('success') do
tests('#list_algorithms').formats(ALGORITHMS_FORMAT) do
@service.list_algorithms.body
end
end
end

View file

@ -0,0 +1,23 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | connection_logging', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
tests('success') do
tests("#get_connection_logging(#{@lb.id})").formats(CONNECTION_LOGGING_FORMAT) do
@service.get_connection_logging(@lb.id).body
end
@lb.wait_for { ready? }
tests("#set_connection_logging(#{@lb.id}, true)").succeeds do
@service.set_connection_logging(@lb.id, true)
end
end
tests('failure') do
tests("#set_connection_logging(#{@lb.id}, 'aaa')").raises(Fog::Rackspace::LoadBalancer::InternalServerError) do
@service.set_connection_logging(@lb.id, 'aaa')
end
end
end
end
end

View file

@ -0,0 +1,35 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | connection_throttling', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
tests('success') do
@lb.wait_for { ready? }
tests("#get_connection_throttling(#{@lb.id})").formats(CONNECTION_THROTTLING_FORMAT) do
@service.get_connection_throttling(@lb.id).body
end
@lb.wait_for { ready? }
tests("#set_connection_throttling(#{@lb.id}, 10, 10, 10, 30)").succeeds do
@service.set_connection_throttling(@lb.id, 10, 10, 10, 30)
end
@lb.wait_for { ready? }
tests("#get_connection_throttling(#{@lb.id})").formats(CONNECTION_THROTTLING_FORMAT) do
@service.get_connection_throttling(@lb.id).body
end
@lb.wait_for { ready? }
tests("#remove_connection_throttling()").succeeds do
@service.remove_connection_throttling(@lb.id)
end
end
tests('failure') do
tests("#set_connection_throttling(#{@lb.id}, -1, -1, -1, -1)").raises(Fog::Rackspace::LoadBalancer::BadRequest) do
@service.set_connection_throttling(@lb.id, -1, -1, -1, -1)
end
end
end
end
end

View file

@ -0,0 +1,112 @@
SINGLE_NODE_FORMAT = {'address' => String, 'id' => Integer, 'status' => String, 'weight' => Fog::Nullable::Integer, 'port' => Integer, 'condition' => String}
NODE_FORMAT = {'node' => SINGLE_NODE_FORMAT}
NODES_FORMAT = {'nodes' => [SINGLE_NODE_FORMAT]}
VIRTUAL_IP_FORMAT = {'type' => String, 'id' => Integer, 'type' => String, 'ipVersion' => String, 'address' => String}
VIRTUAL_IPS_FORMAT = { 'virtualIps' => [VIRTUAL_IP_FORMAT] }
LOAD_BALANCER_USAGE_FORMAT = {
'loadBalancerUsageRecords' => [
{
'id' => Fog::Nullable::Integer,
'eventType' => Fog::Nullable::String,
'averageNumConnections' => Fog::Nullable::Float,
'incomingTransfer' => Fog::Nullable::Integer,
'outgoingTransfer' => Fog::Nullable::Integer,
'numVips' => Fog::Nullable::Integer,
'numPolls' => Fog::Nullable::Integer,
'startTime' => Fog::Nullable::String,
'endTime' => Fog::Nullable::String
}
]
}
USAGE_FORMAT = {
'accountId' => Integer,
'loadBalancerUsages' => [
{
'loadBalancerId' => Fog::Nullable::Integer,
'loadBalancerName' => Fog::Nullable::String
}.merge(LOAD_BALANCER_USAGE_FORMAT)
],
'accountUsage' => [
{
'startTime' => Fog::Nullable::String,
'numLoadBalancers' => Fog::Nullable::Integer,
'numPublicVips' => Fog::Nullable::Integer,
'numServicenetVips' => Fog::Nullable::Integer
}
]
}
CONNECTION_LOGGING_FORMAT = {
'connectionLogging' => {
'enabled' => Fog::Boolean
}
}
CONNECTION_THROTTLING_FORMAT = {
'connectionThrottle' => {
'maxConnections' => Fog::Nullable::Integer,
'minConnections' => Fog::Nullable::Integer,
'maxConnectionRate' => Fog::Nullable::Integer,
'rateInterval' => Fog::Nullable::Integer
}
}
SESSION_PERSISTENCE_FORMAT = {
'sessionPersistence' => {
'persistenceType' => Fog::Nullable::String
}
}
ACCESS_LIST_FORMAT = {
'accessList' => [
{
'address' => String,
'id' => Integer,
'type' => String
}
]
}
HEALTH_MONITOR_FORMAT = {
'healthMonitor' => {
'type' => Fog::Nullable::String,
'delay' => Fog::Nullable::Integer,
'timeout' => Fog::Nullable::Integer,
'attemptsBeforeDeactivation' => Fog::Nullable::Integer,
'path' => Fog::Nullable::String,
'bodyRegex' => Fog::Nullable::String,
'statusRegex' => Fog::Nullable::String
}
}
STATUS_ACTIVE = 'ACTIVE'
LOAD_BALANCERS_FORMAT = {
'loadBalancers' => [
{
'name' => String,
'id' => Integer,
'port' => Integer,
'protocol' => String,
'algorithm' => String,
'status' => String,
'virtualIps' => [VIRTUAL_IP_FORMAT],
'nodes' => [SINGLE_NODE_FORMAT],
'created' => { 'time' => String },
'updated' => { 'time' => String }
}]
}
LOAD_BALANCER_FORMAT = {
'loadBalancer' => {
'name' => String,
'id' => Integer,
'port' => Integer,
'protocol' => String,
'algorithm' => String,
'status' => String,
'cluster' => { 'name' => String },
'virtualIps' => [VIRTUAL_IP_FORMAT],
'nodes' => [SINGLE_NODE_FORMAT],
'created' => { 'time' => String },
'updated' => { 'time' => String },
}.merge(CONNECTION_LOGGING_FORMAT)
}

View file

@ -0,0 +1,61 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | load_balancer_tests', ['rackspace']) do
given_a_load_balancer_service do
tests('success') do
@lb_id = nil
@lb_name = 'fog' + Time.now.to_i.to_s
tests('#create_load_balancer(fog, )').formats(LOAD_BALANCER_FORMAT) do
data = @service.create_load_balancer(@lb_name, 'HTTP', 80, [{ :type => 'PUBLIC'}], [{ :address => '10.0.0.1', :port => 80, :condition => 'ENABLED'}]).body
@lb_id = data['loadBalancer']['id']
data
end
tests("#update_load_balancer(#{@lb_id}) while immutable").raises(Fog::Rackspace::LoadBalancer::ServiceError) do
@service.update_load_balancer(@lb_id, { :port => 80 }).body
end
tests("#get_load_balancer(#{@lb_id})").formats(LOAD_BALANCER_FORMAT) do
@service.get_load_balancer(@lb_id).body
end
tests("#list_load_balancers()").formats(LOAD_BALANCERS_FORMAT) do
@service.list_load_balancers.body
end
until @service.get_load_balancer(@lb_id).body["loadBalancer"]["status"] == STATUS_ACTIVE
sleep 10
end
tests("#update_load_balancer(#{lb_id}, { :port => 80 })").succeeds do
@service.update_load_balancer(@lb_id, { :port => 80 }).body
end
until @service.get_load_balancer(@lb_id).body["loadBalancer"]["status"] == STATUS_ACTIVE
sleep 10
end
tests("#delete_load_balancer(#{@ld_id})").succeeds do
@service.delete_load_balancer(@lb_id).body
end
end
tests('failure') do
tests('#create_load_balancer(invalid name)').raises(Fog::Rackspace::LoadBalancer::BadRequest) do
@service.create_load_balancer('', 'HTTP', 80, [{ :type => 'PUBLIC'}], [{ :address => '10.0.0.1', :port => 80, :condition => 'ENABLED'}])
end
tests('#get_load_balancer(0)').raises(Fog::Rackspace::LoadBalancer::NotFound) do
@service.get_load_balancer(0)
end
tests('#delete_load_balancer(0)').raises(Fog::Rackspace::LoadBalancer::NotFound) do
@service.delete_load_balancer(0)
end
tests('#update_load_balancer(0)').raises(Fog::Rackspace::LoadBalancer::NotFound) do
@service.update_load_balancer(0, { :name => 'newname' })
end
end
end
end

View file

@ -0,0 +1,17 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | load_balancer_usage', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
tests('success') do
@lb.wait_for { ready? }
tests("#get_usage(#{@lb.id})").formats(LOAD_BALANCER_USAGE_FORMAT) do
@service.get_load_balancer_usage(@lb.id).body
end
tests("#get_usage(:start_time => '2010-05-10', :end_time => '2010-05-11')").formats(LOAD_BALANCER_USAGE_FORMAT) do
@service.get_load_balancer_usage(@lb.id, :start_time => '2010-05-10', :end_time => '2010-05-11').body
end
end
end
end
end

View file

@ -0,0 +1,44 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | monitor', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
tests('success') do
@lb.wait_for { ready? }
tests("#get_monitor(#{@lb.id})").formats(HEALTH_MONITOR_FORMAT) do
@service.get_monitor(@lb.id).body
end
@lb.wait_for { ready? }
tests("#set_monitor(#{@lb.id}, 'CONNECT', 5, 5, 5)").succeeds do
@service.set_monitor(@lb.id, 'CONNECT', 5, 5, 5)
end
@lb.wait_for { ready? }
tests("#set_monitor(#{@lb.id}, 'HTTP', 5, 5, 5, :path => '/', :body_regex => '^200$', :status_regex => '^2[0-9][0-9]$')").succeeds do
@service.set_monitor(@lb.id, 'HTTP', 5, 5, 5, :path => '/', :body_regex => '^200$', :status_regex => '2[0-9][0-9]$')
end
@lb.wait_for { ready? }
tests("#get_monitor(#{@lb.id})").formats(HEALTH_MONITOR_FORMAT) do
@service.get_monitor(@lb.id).body
end
@lb.wait_for { ready? }
tests("#remove_monitor()").succeeds do
@service.remove_monitor(@lb.id)
end
end
tests('failure') do
tests("#set_monitor(#{@lb.id}, 'HTP', 5, 5, 5, 5)").raises(Fog::Rackspace::LoadBalancer::BadRequest) do
@service.set_monitor(@lb.id, 5, 5, 5, 5)
end
tests("#remove_monitor(#{@lb.id}) => No Monitor").raises(Fog::Rackspace::LoadBalancer::ServiceError) do
@service.remove_monitor(@lb.id)
end
end
end
end
end

View file

@ -0,0 +1,85 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | load_balancer_tests', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
@nodes_created = []
tests('success') do
@lb.wait_for { ready? }
tests('#create_node').formats(NODES_FORMAT) do
data = @service.create_node(@lb.id, '10.10.10.10', 80, 'ENABLED').body
@nodes_created << data['nodes'][0]['id']
data
end
@lb.wait_for { ready? }
tests('#create_node with weight').formats(NODES_FORMAT) do
data = @service.create_node(@lb.id, '10.10.10.11', 80, 'ENABLED', { :weight => 10 }).body
@nodes_created << data['nodes'][0]['id']
data
end
@lb.wait_for { ready? }
tests("list_nodes").formats(NODES_FORMAT) do
@service.list_nodes(@lb.id).body
end
@lb.wait_for { ready? }
tests("get_node(#{@lb_node_id})").formats(NODE_FORMAT) do
@service.get_node(@lb.id, @nodes_created[0]).body
end
tests("update_node(#{@lb.id}, #{@nodes_created[0]})").succeeds do
@lb.wait_for { ready? }
tests("condition").succeeds do
@service.update_node(@lb.id, @nodes_created[0], { :condition => 'DISABLED' })
end
@lb.wait_for { ready? }
tests("weight").succeeds do
@service.update_node(@lb.id, @nodes_created[0], { :weight => 20 })
end
@lb.wait_for { ready? }
tests("condition and weight").succeeds do
@service.update_node(@lb.id, @nodes_created[0], { :condition => 'DISABLED', :weight => 20 })
end
end
end
tests('failure') do
tests('create_node(invalid ip)').raises(Fog::Rackspace::LoadBalancer::BadRequest) do
@service.create_node(@lb.id, '', 80, 'ENABLED')
end
tests('create_node(invalid condition)').raises(Fog::Rackspace::LoadBalancer::BadRequest) do
@service.create_node(@lb.id, '10.10.10.10', 80, 'EABLED')
end
tests('get_node(0)').raises(Fog::Rackspace::LoadBalancer::NotFound) do
@service.get_node(@lb.id, 0)
end
tests('delete_nodes(0)').raises(Fog::Rackspace::LoadBalancer::ServiceError) do
@service.delete_nodes(@lb.id, 0)
end
tests('update_node(0)').raises(Fog::Rackspace::LoadBalancer::NotFound) do
@service.update_node(@lb.id, 0, { :weight => 20 })
end
end
tests('success') do
@lb.wait_for { ready? }
tests("#delete_nodes(multiple node)").succeeds do
pending
@service.delete_nodes(@lb.id, *@nodes_created)
end
@lb.wait_for { ready? }
tests("#delete_node()").succeeds do
node_id = @service.create_node(@lb.id, '10.10.10.12', 80, 'ENABLED').body['nodes'][0]['id']
@lb.wait_for { ready? }
@service.delete_node(@lb.id, node_id)
end
end
end
end
end

View file

@ -0,0 +1,19 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | protocol_tests', ['rackspace']) do
PROTOCOLS_FORMAT = {
'protocols' => [
{
'name' => String,
'port' => Integer
}
]}
@service = Fog::Rackspace::LoadBalancer.new
tests('success') do
tests('#list_protocols').formats(PROTOCOLS_FORMAT) do
@service.list_protocols.body
end
end
end

View file

@ -0,0 +1,31 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | session_persistence', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
tests('success') do
@lb.wait_for { ready? }
tests("#set_session_persistence(#{@lb.id}, 'HTTP_COOKIE')").succeeds do
@service.set_session_persistence(@lb.id, 'HTTP_COOKIE')
end
@lb.wait_for { ready? }
tests("#get_session_persistence{@lb.id})").formats(SESSION_PERSISTENCE_FORMAT) do
data = @service.get_session_persistence(@lb.id).body
returns('HTTP_COOKIE') { data['sessionPersistence']['persistenceType'] }
data
end
@lb.wait_for { ready? }
tests("#remove_session_persistence()").succeeds do
@service.remove_session_persistence(@lb.id)
end
end
tests('failure') do
tests("#set_session_persistence(#{@lb.id}, 'aaa')").raises(Fog::Rackspace::LoadBalancer::BadRequest) do
@service.set_session_persistence(@lb.id, 'aaa')
end
end
end
end
end

View file

@ -0,0 +1,15 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | usage', ['rackspace']) do
given_a_load_balancer_service do
tests('success') do
tests("#get_usage()").formats(USAGE_FORMAT) do
@service.get_usage.body
end
tests("#get_usage(:start_time => '2010-05-10', :end_time => '2010-05-11')").formats(USAGE_FORMAT) do
@service.get_usage(:start_time => '2010-05-10', :end_time => '2010-05-11').body
end
end
end
end

View file

@ -0,0 +1,38 @@
Shindo.tests('Fog::Rackspace::LoadBalancer | virtual_ip_tests', ['rackspace']) do
given_a_load_balancer_service do
given_a_load_balancer do
tests('success') do
@lb.wait_for { ready? }
tests('#create_virtual_ip').formats(VIRTUAL_IP_FORMAT) do
data = @service.create_virtual_ip(@lb.id, 'PUBLIC').body
@virtual_ip_id = data['id']
data
end
@lb.wait_for { ready? }
tests("list_virtual_ips").formats(VIRTUAL_IPS_FORMAT) do
@service.list_virtual_ips(@lb.id).body
end
end
tests('failure') do
#TODO - I feel like this should really be a BadRequest, need to dig in
tests('create_virtual_ip(invalid type)').raises(Fog::Rackspace::LoadBalancer::ServiceError) do
@service.create_virtual_ip(@lb.id, 'badtype')
end
tests('delete_virtual_ip(0)').raises(Fog::Rackspace::LoadBalancer::NotFound) do
@service.delete_virtual_ip(@lb.id, 0)
end
end
tests('success') do
@lb.wait_for { ready? }
tests("#delete_virtual_ip(#{@lb.id}, #{@virtual_ip_id})").succeeds do
@service.delete_virtual_ip(@lb.id, @virtual_ip_id)
end
end
end
end
end