mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
[rackspace|autoscale] starting on rackspace auto scale implementation
This commit is contained in:
parent
db5d9f0813
commit
bf0dac91b0
12 changed files with 451 additions and 0 deletions
|
@ -3,6 +3,8 @@ class Rackspace < Fog::Bin
|
|||
|
||||
def class_for(key)
|
||||
case key
|
||||
when :auto_scale
|
||||
Fog::Rackspace::AutoScale
|
||||
when :block_storage
|
||||
Fog::Rackspace::BlockStorage
|
||||
when :cdn
|
||||
|
@ -29,6 +31,8 @@ class Rackspace < Fog::Bin
|
|||
def [](service)
|
||||
@@connections ||= Hash.new do |hash, key|
|
||||
hash[key] = case key
|
||||
when :auto_scale
|
||||
Fog::Rackspace::AutoScale.new
|
||||
when :cdn
|
||||
Fog::Logger.warning("Rackspace[:cdn] is not recommended, use CDN[:rackspace] for portability")
|
||||
Fog::CDN.new(:provider => 'Rackspace')
|
||||
|
|
|
@ -72,6 +72,7 @@ module Fog
|
|||
end
|
||||
end
|
||||
|
||||
service(:auto_scale, 'rackspace/auto_scale', 'AutoScale')
|
||||
service(:block_storage, 'rackspace/block_storage', 'BlockStorage')
|
||||
service(:cdn, 'rackspace/cdn', 'CDN')
|
||||
service(:compute, 'rackspace/compute', 'Compute')
|
||||
|
|
103
lib/fog/rackspace/auto_scale.rb
Normal file
103
lib/fog/rackspace/auto_scale.rb
Normal file
|
@ -0,0 +1,103 @@
|
|||
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rackspace'))
|
||||
|
||||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale < Fog::Service
|
||||
include Fog::Rackspace::Errors
|
||||
|
||||
class ServiceError < Fog::Rackspace::Errors::ServiceError; end
|
||||
class InternalServerError < Fog::Rackspace::Errors::InternalServerError; end
|
||||
|
||||
class BadRequest < Fog::Rackspace::Errors::BadRequest
|
||||
attr_reader :validation_errors
|
||||
|
||||
def self.slurp(error)
|
||||
if error && error.response
|
||||
status_code = error.response.status
|
||||
if error.response.body
|
||||
body = Fog::JSON.decode(error.response.body)
|
||||
message = "#{body['type']} - #{body['message']}"
|
||||
details = error.response.body['details']
|
||||
end
|
||||
end
|
||||
|
||||
new_error = new(message)
|
||||
new_error.set_backtrace(error.backtrace)
|
||||
new_error.instance_variable_set(:@validation_errors, details)
|
||||
new_error.instance_variable_set(:@status_code, status_code)
|
||||
|
||||
new_error
|
||||
end
|
||||
end
|
||||
|
||||
requires :rackspace_username, :rackspace_api_key
|
||||
recognizes :rackspace_auth_url
|
||||
recognizes :rackspace_region
|
||||
recognizes :rackspace_auto_scale_url
|
||||
|
||||
model_path 'fog/rackspace/models/auto_scale'
|
||||
|
||||
request_path 'fog/rackspace/requests/auto_scale'
|
||||
request :list_groups
|
||||
request :get_group
|
||||
request :create_group
|
||||
request :delete_group
|
||||
request :get_group_state
|
||||
|
||||
request :update_config
|
||||
request :get_config
|
||||
|
||||
class Mock < Fog::Rackspace::Service
|
||||
def initialize(options)
|
||||
@rackspace_api_key = options[:rackspace_api_key]
|
||||
end
|
||||
|
||||
def request(params)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class Real < Fog::Rackspace::Service
|
||||
|
||||
def initialize(options = {})
|
||||
@options = options
|
||||
@options[:connection_options] ||= {}
|
||||
@options[:persistent] ||= false
|
||||
|
||||
authenticate
|
||||
|
||||
@connection = Fog::Connection.new(endpoint_uri.to_s, @options[:persistent], @options[:connection_options])
|
||||
end
|
||||
|
||||
def request(params, parse_json = true, &block)
|
||||
super(params, parse_json, &block)
|
||||
rescue Excon::Errors::NotFound => error
|
||||
raise NotFound.slurp(error, region)
|
||||
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
|
||||
|
||||
def endpoint_uri(service_endpoint_url=nil)
|
||||
@uri = super(@options[:rackspace_auto_scale_url], :rackspace_auto_scale_url)
|
||||
end
|
||||
|
||||
def authenticate(options={})
|
||||
super(select_options([:rackspace_username, :rackspace_api_key, :rackspace_auth_url, :connection_options]))
|
||||
end
|
||||
|
||||
def service_name
|
||||
:autoscale
|
||||
end
|
||||
|
||||
def region
|
||||
@options[:rackspace_region]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
88
lib/fog/rackspace/requests/auto_scale/create_group.rb
Normal file
88
lib/fog/rackspace/requests/auto_scale/create_group.rb
Normal file
|
@ -0,0 +1,88 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Real
|
||||
|
||||
def create_group
|
||||
request(
|
||||
:expects => [201],
|
||||
:method => 'POST',
|
||||
:path => 'groups',
|
||||
:body => <<-JSON
|
||||
{
|
||||
\"groupConfiguration\": {
|
||||
\"name\": \"workers2\",
|
||||
\"cooldown\": 60,
|
||||
\"minEntities\": 5,
|
||||
\"maxEntities\": 25,
|
||||
\"metadata\": {
|
||||
\"firstkey\": \"this is a string\",
|
||||
\"secondkey\": \"1\"
|
||||
}
|
||||
},
|
||||
\"launchConfiguration\": {
|
||||
\"type\": \"launch_server\",
|
||||
\"args\": {
|
||||
\"server\": {
|
||||
\"flavorRef\": 3,
|
||||
\"name\": \"webhead\",
|
||||
\"imageRef\": \"0d589460-f177-4b0f-81c1-8ab8903ac7d8\",
|
||||
\"OS-DCF:diskConfig\": \"AUTO\",
|
||||
\"metadata\": {
|
||||
\"mykey\": \"myvalue\"
|
||||
},
|
||||
\"personality\": [
|
||||
{
|
||||
\"path\": \"/root/.ssh/authorized_keys\",
|
||||
\"contents\": \"ssh-rsa AAAAB3Nza...LiPk== user@example.net\"
|
||||
}
|
||||
],
|
||||
\"networks\": [
|
||||
{
|
||||
\"uuid\": \"11111111-1111-1111-1111-111111111111\"
|
||||
}
|
||||
]
|
||||
},
|
||||
\"loadBalancers\": [
|
||||
{
|
||||
\"loadBalancerId\": 2200,
|
||||
\"port\": 8081
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
\"scalingPolicies\": [
|
||||
{
|
||||
\"name\": \"scale up by 10\",
|
||||
\"change\": 10,
|
||||
\"cooldown\": 5,
|
||||
\"type\": \"webhook\"
|
||||
},
|
||||
{
|
||||
\"name\": \"scale down by 5.5 percent\",
|
||||
\"changePercent\": -5.5,
|
||||
\"cooldown\": 6,
|
||||
\"type\": \"webhook\"
|
||||
},
|
||||
{
|
||||
\"name\": \"set number of servers to 10\",
|
||||
\"desiredCapacity\": 10,
|
||||
\"cooldown\": 3,
|
||||
\"type\": \"webhook\"
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def create_group
|
||||
Fog::Mock.not_implemented
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
22
lib/fog/rackspace/requests/auto_scale/delete_group.rb
Normal file
22
lib/fog/rackspace/requests/auto_scale/delete_group.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Real
|
||||
|
||||
def delete_group(group_id)
|
||||
request(
|
||||
:expects => [204],
|
||||
:method => 'DELETE',
|
||||
:path => "groups/#{group_id}"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def delete_group(group_id)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
24
lib/fog/rackspace/requests/auto_scale/get_config.rb
Normal file
24
lib/fog/rackspace/requests/auto_scale/get_config.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
|
||||
class Real
|
||||
|
||||
def get_config(group_id)
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "groups/#{group_id}/config",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def get_config(group_id)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
24
lib/fog/rackspace/requests/auto_scale/get_group.rb
Normal file
24
lib/fog/rackspace/requests/auto_scale/get_group.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
|
||||
class Real
|
||||
|
||||
def get_group(group_id)
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "groups/#{group_id}",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def get_group(group_id)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
24
lib/fog/rackspace/requests/auto_scale/get_group_state.rb
Normal file
24
lib/fog/rackspace/requests/auto_scale/get_group_state.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
|
||||
class Real
|
||||
|
||||
def get_group_state(group_id)
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => "groups/#{group_id}/state",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def get_group_state(group_id)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
35
lib/fog/rackspace/requests/auto_scale/list_groups.rb
Normal file
35
lib/fog/rackspace/requests/auto_scale/list_groups.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
class Real
|
||||
|
||||
# Retrieves a list of images
|
||||
# @return [Excon::Response] response:
|
||||
# * body [Hash]:
|
||||
# * images [Array]:
|
||||
# * [Hash]:
|
||||
# * id [String] - flavor id
|
||||
# * links [Array] - image links
|
||||
# * name [String] - image name
|
||||
# @raise [Fog::Compute::RackspaceV2::NotFound] - HTTP 404
|
||||
# @raise [Fog::Compute::RackspaceV2::BadRequest] - HTTP 400
|
||||
# @raise [Fog::Compute::RackspaceV2::InternalServerError] - HTTP 500
|
||||
# @raise [Fog::Compute::RackspaceV2::ServiceError]
|
||||
# @see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Flavors-d1e4188.html
|
||||
def list_groups
|
||||
request(
|
||||
:expects => [200],
|
||||
:method => 'GET',
|
||||
:path => 'groups'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def list_groups
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
37
lib/fog/rackspace/requests/auto_scale/update_config.rb
Normal file
37
lib/fog/rackspace/requests/auto_scale/update_config.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
module Fog
|
||||
module Rackspace
|
||||
class AutoScale
|
||||
|
||||
class Real
|
||||
|
||||
def update_config(group_id)
|
||||
|
||||
h = {
|
||||
"name" => "workers",
|
||||
"cooldown" => 60,
|
||||
"minEntities" => 0,
|
||||
"maxEntities" => 0,
|
||||
"metadata" => {
|
||||
"firstkey" => "this is a string",
|
||||
"secondkey" => "1"
|
||||
}
|
||||
}
|
||||
|
||||
request(
|
||||
:expects => [204],
|
||||
:method => 'PUT',
|
||||
:path => "groups/#{group_id}/config",
|
||||
:body => Fog::JSON.encode(h)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def update_config(group_id)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -116,6 +116,11 @@ module Fog
|
|||
@auth_token || @identity_service.auth_token
|
||||
end
|
||||
|
||||
def select_options(keys)
|
||||
return nil unless @options && keys
|
||||
@options.select {|k,v| keys.include?(k)}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
84
tests/rackspace/auto_scale_tests.rb
Normal file
84
tests/rackspace/auto_scale_tests.rb
Normal file
|
@ -0,0 +1,84 @@
|
|||
Shindo.tests('Fog::Rackspace::AutoScale', ['rackspace']) do
|
||||
|
||||
def assert_method(url, method)
|
||||
@service.instance_variable_set "@rackspace_auth_url", url
|
||||
returns(method) { @service.send :authentication_method }
|
||||
end
|
||||
|
||||
tests('#authentication_method') do
|
||||
@service = Fog::Rackspace::AutoScale.new :rackspace_region => :dfw
|
||||
|
||||
assert_method nil, :authenticate_v2
|
||||
|
||||
assert_method 'auth.api.rackspacecloud.com', :authenticate_v1 # chef's default auth endpoint
|
||||
|
||||
assert_method 'https://identity.api.rackspacecloud.com', :authenticate_v1
|
||||
assert_method 'https://identity.api.rackspacecloud.com/v1', :authenticate_v1
|
||||
assert_method 'https://identity.api.rackspacecloud.com/v1.1', :authenticate_v1
|
||||
assert_method 'https://identity.api.rackspacecloud.com/v2.0', :authenticate_v2
|
||||
|
||||
assert_method 'https://lon.identity.api.rackspacecloud.com', :authenticate_v1
|
||||
assert_method 'https://lon.identity.api.rackspacecloud.com/v1', :authenticate_v1
|
||||
assert_method 'https://lon.identity.api.rackspacecloud.com/v1.1', :authenticate_v1
|
||||
assert_method 'https://lon.identity.api.rackspacecloud.com/v2.0', :authenticate_v2
|
||||
end
|
||||
|
||||
|
||||
tests('current authentation') do
|
||||
pending if Fog.mocking?
|
||||
|
||||
tests('variables populated').succeeds do
|
||||
@service = Fog::Rackspace::AutoScale.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v2.0', :connection_options => {:ssl_verify_peer => true}, :rackspace_region => :dfw
|
||||
returns(true, "auth token populated") { !@service.send(:auth_token).nil? }
|
||||
returns(false, "path populated") { @service.instance_variable_get("@uri").host.nil? }
|
||||
identity_service = @service.instance_variable_get("@identity_service")
|
||||
returns(false, "identity service was used") { identity_service.nil? }
|
||||
returns(true, "connection_options are passed") { identity_service.instance_variable_get("@connection_options").has_key?(:ssl_verify_peer) }
|
||||
@service.list_groups
|
||||
end
|
||||
tests('dfw region').succeeds do
|
||||
@service = Fog::Rackspace::AutoScale.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v2.0', :rackspace_region => :dfw
|
||||
returns(true, "auth token populated") { !@service.send(:auth_token).nil? }
|
||||
returns(true) { (@service.instance_variable_get("@uri").host =~ /dfw/) != nil }
|
||||
@service.list_groups
|
||||
end
|
||||
tests('ord region').succeeds do
|
||||
@service = Fog::Rackspace::AutoScale.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v2.0', :rackspace_region => :ord
|
||||
returns(true, "auth token populated") { !@service.send(:auth_token).nil? }
|
||||
returns(true) { (@service.instance_variable_get("@uri").host =~ /ord/) != nil }
|
||||
@service.list_groups
|
||||
end
|
||||
tests('custom endpoint') do
|
||||
@service = Fog::Rackspace::AutoScale.new :rackspace_auth_url => 'https://identity.api.rackspacecloud.com/v2.0',
|
||||
:rackspace_auto_scale_url => 'https://my-custom-endpoint.com'
|
||||
returns(true, "auth token populated") { !@service.send(:auth_token).nil? }
|
||||
returns(true, "uses custom endpoint") { (@service.instance_variable_get("@uri").host =~ /my-custom-endpoint\.com/) != nil }
|
||||
end
|
||||
end
|
||||
|
||||
tests('default auth') do
|
||||
pending if Fog.mocking?
|
||||
|
||||
tests('specify region').succeeds do
|
||||
@service = Fog::Rackspace::AutoScale.new :rackspace_region => :ord
|
||||
returns(true, "auth token populated") { !@service.send(:auth_token).nil? }
|
||||
returns(true) { (@service.instance_variable_get("@uri").host =~ /ord/ ) != nil }
|
||||
@service.list_groups
|
||||
end
|
||||
tests('custom endpoint') do
|
||||
@service = Fog::Rackspace::AutoScale.new :rackspace_auto_scale_url => 'https://my-custom-endpoint.com'
|
||||
returns(true, "auth token populated") { !@service.send(:auth_token).nil? }
|
||||
returns(true, "uses custom endpoint") { (@service.instance_variable_get("@uri").host =~ /my-custom-endpoint\.com/) != nil }
|
||||
end
|
||||
end
|
||||
|
||||
tests('reauthentication') do
|
||||
pending if Fog.mocking?
|
||||
|
||||
@service = Fog::Rackspace::AutoScale.new :rackspace_region => :ord
|
||||
returns(true, "auth token populated") { !@service.send(:auth_token).nil? }
|
||||
@service.instance_variable_set("@auth_token", "bad_token")
|
||||
returns(true) { [200, 203].include? @service.list_groups.status }
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue