diff --git a/lib/fog/bin/rackspace.rb b/lib/fog/bin/rackspace.rb index 833f33dc4..1a4be3553 100644 --- a/lib/fog/bin/rackspace.rb +++ b/lib/fog/bin/rackspace.rb @@ -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 diff --git a/lib/fog/providers/rackspace.rb b/lib/fog/providers/rackspace.rb index b444d1a65..197706bbd 100644 --- a/lib/fog/providers/rackspace.rb +++ b/lib/fog/providers/rackspace.rb @@ -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" diff --git a/lib/fog/rackspace/load_balancer.rb b/lib/fog/rackspace/load_balancer.rb new file mode 100644 index 000000000..6da7f2beb --- /dev/null +++ b/lib/fog/rackspace/load_balancer.rb @@ -0,0 +1,76 @@ +module Fog + module Rackspace + class LoadBalancer < Fog::Service + + DFW_ENDPOINT = 'https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/' + ORD_ENDPOINT = 'https://ord.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' + + request_path 'fog/rackspace/requests' + request :create_load_balancer + request :delete_load_balancer + + 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 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::HTTPStatusError => error + raise case error + when Excon::Errors::NotFound + Fog::Compute::Rackspace::NotFound.slurp(error) + else + error + end + 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 + end + end + end +end + diff --git a/lib/fog/rackspace/requests/create_load_balancer.rb b/lib/fog/rackspace/requests/create_load_balancer.rb new file mode 100644 index 000000000..31a35432e --- /dev/null +++ b/lib/fog/rackspace/requests/create_load_balancer.rb @@ -0,0 +1,30 @@ +module Fog + module Rackspace + class LoadBalancer + class Real + def create_load_balancer(options = {}) + data = { + 'loadBalancer' => { + 'name' => options[:name], + 'port' => options[:port], + 'protocol' => options[:protocol], + 'virtualIps' => options[:virtualIps], + 'nodes' => options[:nodes] + } + } + 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 diff --git a/lib/fog/rackspace/requests/delete_load_balancer.rb b/lib/fog/rackspace/requests/delete_load_balancer.rb new file mode 100644 index 000000000..f7afc5f89 --- /dev/null +++ b/lib/fog/rackspace/requests/delete_load_balancer.rb @@ -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}", + :method => 'DELETE' + ) + end + end + class Mock + def delete_load_balancer(load_balancer_id) + Fog::Mock.not_implemented + end + end + end + end +end diff --git a/tests/rackspace/requests/load_balancer_tests.rb b/tests/rackspace/requests/load_balancer_tests.rb new file mode 100644 index 000000000..5c13b041d --- /dev/null +++ b/tests/rackspace/requests/load_balancer_tests.rb @@ -0,0 +1,41 @@ +Shindo.tests('Fog::Rackspace::LoadBalancer | load_balancer_tests', ['rackspace']) do + + @load_balancer_format = { + 'loadBalancer' => { + 'name' => String, + 'id' => Integer, + 'port' => Integer, + 'protocol' => String, + 'algorithm' => String, + 'status' => String, + 'cluster' => { 'name' => String }, + 'virtualIps' => [{'type' => String, 'id' => Integer, 'type' => String, 'ipVersion' => String, 'address' => String}], + 'nodes' => [{'address' => String, 'id' => Integer, 'status' => String, 'weight' => Integer, 'port' => Integer, 'condition' => String}], + 'created' => { 'time' => String }, + 'updated' => { 'time' => String }, + 'connectionLogging' => { 'enabled' => Fog::Boolean } + }} + + tests('success') do + + @lb_id = nil + @lb = Fog::Rackspace::LoadBalancer.new + + tests('#create_lb()').formats(@load_balancer_format) do + data = @lb.create_load_balancer(:name => 'fog' + Time.now.to_i.to_s, :port => '80', :protocol => 'HTTP', :virtualIps => [{ :type => 'PUBLIC'}], :nodes => [{ :address => '10.0.0.1', :port => 80, :condition => 'ENABLED'}]).body + puts data + @lb_id = data['loadBalancer']['id'] + data + end + + puts "Sleeping..." + sleep(60) + + tests("#delete_load_balancer(#{@ld_id})").succeeds do + @lb.delete_load_balancer(@lb_id) + end + end + + tests('failure') do + end +end