diff --git a/lib/fog/rackspace/load_balancer.rb b/lib/fog/rackspace/load_balancer.rb index 3036b1e26..fdb867610 100644 --- a/lib/fog/rackspace/load_balancer.rb +++ b/lib/fog/rackspace/load_balancer.rb @@ -23,6 +23,7 @@ module Fog 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) @@ -44,6 +45,8 @@ module Fog model_path 'fog/rackspace/models' collection :load_balancers model :load_balancer + collection :nodes + model :node request_path 'fog/rackspace/requests' request :create_load_balancer diff --git a/lib/fog/rackspace/models/load_balancer.rb b/lib/fog/rackspace/models/load_balancer.rb index a51933d9e..77e2d4ee9 100644 --- a/lib/fog/rackspace/models/load_balancer.rb +++ b/lib/fog/rackspace/models/load_balancer.rb @@ -13,24 +13,30 @@ module Fog attribute :protocol attribute :algorithm attribute :virtual_ips, :aliases => 'virtualIps' - attribute :nodes attribute :created attribute :updated attribute :name attribute :state, :aliases => 'status' - def initialize(attributes={}) - super + def nodes + @nodes + end + + def nodes=(new_nodes) + @nodes = Fog::Rackspace::LoadBalancer::Nodes.new({ + :connection => connection, + :load_balancer => self}) + @nodes.load(new_nodes) end def destroy - requires :id - connection.delete_load_balancer(id) + requires :identity + connection.delete_load_balancer(identity) true end def ready? - self.state == 'ACTIVE' + state == 'ACTIVE' end def save @@ -45,18 +51,21 @@ module Fog private def create requires :name, :protocol, :port, :virtual_ips, :nodes - data = connection.create_load_balancer(name, protocol, port, virtual_ips, nodes) + data = connection.create_load_balancer(name, protocol, port, virtual_ips, nodes.to_object) merge_attributes(data.body['loadBalancer']) end def update - requires :name, :protool, :port, :algorithm + requires :name, :protocol, :port, :algorithm options = { - 'name' => name, - 'algorithm' => algorithm, - 'protocol' => protocol, - 'port' => port} + :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 end end diff --git a/lib/fog/rackspace/models/node.rb b/lib/fog/rackspace/models/node.rb new file mode 100644 index 000000000..3333a4146 --- /dev/null +++ b/lib/fog/rackspace/models/node.rb @@ -0,0 +1,62 @@ +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 + + def to_object + { :address => address, :port => port, :condition => condition, :weight => weight } + 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 diff --git a/lib/fog/rackspace/models/nodes.rb b/lib/fog/rackspace/models/nodes.rb new file mode 100644 index 000000000..5a763ff1b --- /dev/null +++ b/lib/fog/rackspace/models/nodes.rb @@ -0,0 +1,39 @@ +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 + data = connection.list_nodes(load_balancer.id).body['nodes'] + load(data) + end + + def get(node_id) + if node = connection.get_node(load_balancer.id, node_id).body['node'] + new(node) + end + rescue Fog::Rackspace::LoadBalancer::NotFound + nil + end + + def save + each do |node| + node.save + end + end + + def to_object + collect do |node| + node.to_object + end + end + end + end + end +end diff --git a/tests/rackspace/models/load_balancer_tests.rb b/tests/rackspace/models/load_balancer_tests.rb index 709d7e698..a3cf4185e 100644 --- a/tests/rackspace/models/load_balancer_tests.rb +++ b/tests/rackspace/models/load_balancer_tests.rb @@ -11,5 +11,12 @@ Shindo.tests('Fog::Rackspace::LoadBalancer | load_balancer', ['rackspace']) do }, 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? } end end diff --git a/tests/rackspace/models/load_balancers_tests.rb b/tests/rackspace/models/load_balancers_tests.rb index 4d45fa170..798d806b8 100644 --- a/tests/rackspace/models/load_balancers_tests.rb +++ b/tests/rackspace/models/load_balancers_tests.rb @@ -11,12 +11,5 @@ Shindo.tests('Fog::Rackspace::LoadBalancer | load_balancers', ['rackspace']) do }, false) do @instance.wait_for { ready? } - - tests('saving existing load balancer').succeeds do - @instance.port = 88 - @instance.save - end - - @instance.wait_for { ready? } end end diff --git a/tests/rackspace/models/node_tests.rb b/tests/rackspace/models/node_tests.rb new file mode 100644 index 000000000..16479c24a --- /dev/null +++ b/tests/rackspace/models/node_tests.rb @@ -0,0 +1,28 @@ +Shindo.tests('Fog::Rackspace::LoadBalancer | node', ['rackspace']) do + + @service = Fog::Rackspace::LoadBalancer.new + @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 + 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 + ensure + @lb.wait_for { ready? } + @lb.destroy + end +end diff --git a/tests/rackspace/models/nodes_tests.rb b/tests/rackspace/models/nodes_tests.rb new file mode 100644 index 000000000..0ca50be4e --- /dev/null +++ b/tests/rackspace/models/nodes_tests.rb @@ -0,0 +1,21 @@ +Shindo.tests('Fog::Rackspace::LoadBalancer | nodes', ['rackspace']) do + + @service = Fog::Rackspace::LoadBalancer.new + @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 + collection_tests(@lb.nodes, { :address => '10.0.0.2', :port => 80, :condition => 'ENABLED'}, false) do + @lb.wait_for { ready? } + end + ensure + @lb.wait_for { ready? } + @lb.destroy + end +end