awsborn 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,7 @@
1
1
  module Awsborn
2
2
  class Server
3
-
3
+ include Awsborn::AwsConstants
4
+
4
5
  def initialize (name, options = {})
5
6
  @name = name
6
7
  @options = options.dup
@@ -106,8 +107,8 @@ module Awsborn
106
107
 
107
108
  def launch_instance (key_pair)
108
109
  @launch_response = ec2.launch_instance(image_id,
109
- :instance_type => constant(instance_type),
110
- :availability_zone => constant(zone),
110
+ :instance_type => symbol_to_aws_instance_type(instance_type),
111
+ :availability_zone => symbol_to_aws_zone(zone),
111
112
  :key_name => key_pair.name,
112
113
  :group_ids => security_group,
113
114
  :monitoring_enabled => monitor
@@ -233,7 +234,7 @@ module Awsborn
233
234
  tmp.is_a?(String) ? tmp : tmp[architecture]
234
235
  end
235
236
  def architecture
236
- string = constant(instance_type)
237
+ string = symbol_to_aws_instance_type(instance_type)
237
238
  case
238
239
  when INSTANCE_TYPES_32_BIT.include?(string) then :i386
239
240
  when INSTANCE_TYPES_64_BIT.include?(string) then :x64
@@ -296,22 +297,6 @@ module Awsborn
296
297
  end
297
298
  end
298
299
 
299
- AVAILABILITY_ZONES = %w[
300
- us-east-1a us-east-1b us-east-1c us-east-1d
301
- us-west-1a us-west-1b
302
- eu-west-1a eu-west-1b
303
- ap-southeast-1a ap-southeast-1b
304
- ap-northeast-1a ap-northeast-1b
305
- ]
306
- INSTANCE_TYPES_32_BIT = %w[m1.small c1.medium t1.micro]
307
- INSTANCE_TYPES_64_BIT = %w[m1.large m1.xlarge m2.xlarge m2.2xlarge m2.4xlarge c1.xlarge cc1.4xlarge t1.micro]
308
- INSTANCE_TYPES = (INSTANCE_TYPES_32_BIT + INSTANCE_TYPES_64_BIT).uniq
309
- SYMBOL_CONSTANT_MAP = (AVAILABILITY_ZONES + INSTANCE_TYPES).inject({}) { |memo,str| memo[str.tr('-.','_').to_sym] = str; memo }
310
-
311
- def constant (symbol)
312
- SYMBOL_CONSTANT_MAP[symbol]
313
- end
314
-
315
300
  def logger
316
301
  @logger ||= self.class.logger
317
302
  end
@@ -34,14 +34,19 @@ module Awsborn
34
34
  @klass = klass
35
35
  @name = name.to_s
36
36
  @instances = []
37
+ @load_balancers = []
37
38
  self.class.clusters << self
38
39
  end
39
-
40
+
40
41
  def domain (*args)
41
42
  @domain = args.first unless args.empty?
42
43
  @domain
43
44
  end
44
-
45
+
46
+ def load_balancer (name, options={})
47
+ @load_balancers << Awsborn::LoadBalancer.new(name, options)
48
+ end
49
+
45
50
  def server (name, options = {})
46
51
  options = add_domain_to_ip(options)
47
52
  instance = @klass.new name, options
@@ -53,6 +58,7 @@ module Awsborn
53
58
  running, missing = requested.partition { |e| e.running? }
54
59
  refresh_running(running) if running.any?
55
60
  start_missing_instances(missing) if missing.any?
61
+ update_load_balancing(running) unless @load_balancers.empty?
56
62
  end
57
63
 
58
64
  def refresh_running (instances)
@@ -65,6 +71,12 @@ module Awsborn
65
71
  delete_key_pair(instances)
66
72
  end
67
73
 
74
+ def update_load_balancing(running)
75
+ @load_balancers.each do |lb|
76
+ lb.update_with(running).inspect
77
+ end
78
+ end
79
+
68
80
  def generate_key_pair (instances)
69
81
  @key_pair = instances.first.ec2.generate_key_pair
70
82
  end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Awsborn::AwsConstants do
4
+ include Awsborn::AwsConstants
5
+ describe "endpoint_for_zone_and_service" do
6
+ it "should have endpoints for each service and for zones in five regions" do
7
+ endpoint_for_zone_and_service(:eu_west_1a, :ec2).should == 'https://eu-west-1.ec2.amazonaws.com'
8
+ endpoint_for_zone_and_service("eu_west_1b", :ec2).should == 'https://eu-west-1.ec2.amazonaws.com'
9
+ endpoint_for_zone_and_service(:us_west_1b, :ec2).should == 'https://us-west-1.ec2.amazonaws.com'
10
+ endpoint_for_zone_and_service(:us_east_1b, :ec2).should == 'https://us-east-1.ec2.amazonaws.com'
11
+ endpoint_for_zone_and_service(:eu_west_1a, :elb).should == 'https://eu-west-1.elasticloadbalancing.amazonaws.com'
12
+ endpoint_for_zone_and_service("eu_west_1b", :elb).should == 'https://eu-west-1.elasticloadbalancing.amazonaws.com'
13
+ endpoint_for_zone_and_service(:us_west_1b, :elb).should == 'https://us-west-1.elasticloadbalancing.amazonaws.com'
14
+ endpoint_for_zone_and_service(:us_east_1b, :elb).should == 'https://us-east-1.elasticloadbalancing.amazonaws.com'
15
+ end
16
+ end
17
+
18
+ describe "zone_to_awz_region" do
19
+ it "accepts a zone symbol and returns its region" do
20
+ zone_to_awz_region(:eu_west_1a).should == 'eu-west-1'
21
+ end
22
+ it "accepts an aws zone symbol and returns its region" do
23
+ zone_to_awz_region('eu-west-1a').should == 'eu-west-1'
24
+ end
25
+ it "raise an error if no region found" do
26
+ expect{zone_to_awz_region('santa-northpole-2b')}.to raise_error(Awsborn::UnknownConstantError)
27
+ end
28
+ it "returns a region even when a region is given" do
29
+ zone_to_awz_region('eu-west-1').should == 'eu-west-1'
30
+ zone_to_awz_region(:eu_west_1).should == 'eu-west-1'
31
+ end
32
+ end
33
+
34
+ describe "symbol_to_aws_zone" do
35
+ it "accepts a zone symbol and returns its aws zone" do
36
+ symbol_to_aws_zone(:eu_west_1a).should == 'eu-west-1a'
37
+ end
38
+ it "raise an error if no matching aws zone found" do
39
+ expect{symbol_to_aws_zone(:santa_northpole_2b)}.to raise_error(Awsborn::UnknownConstantError)
40
+ end
41
+ end
42
+
43
+ describe "aws_zone_to_symbol" do
44
+ it "returns a symbol from aws zone" do
45
+ aws_zone_to_symbol('eu-west-1a').should == :eu_west_1a
46
+ end
47
+ it "raises an error if the zone is unknown" do
48
+ expect{aws_zone_to_symbol('santa-northpole-2a')}.to raise_error(Awsborn::UnknownConstantError)
49
+ end
50
+ end
51
+
52
+ describe "symbol_to_aws_instance_type" do
53
+ it "accepts an instance type symbol and returns its aws instance type" do
54
+ symbol_to_aws_instance_type(:m1_small).should == 'm1.small'
55
+ end
56
+ it "raise an error if no matching aws zone found" do
57
+ expect{symbol_to_aws_instance_type(:xx_megalarge)}.to raise_error(Awsborn::UnknownConstantError)
58
+ end
59
+ end
60
+
61
+ describe "aws_instance_type_to_symbol" do
62
+ it "returns a symbol from aws instance type" do
63
+ aws_instance_type_to_symbol('m1.small').should == :m1_small
64
+ end
65
+ it "raises an error if the instance type is unknown" do
66
+ expect{aws_instance_type_to_symbol('xx.megalarge')}.to raise_error(Awsborn::UnknownConstantError)
67
+ end
68
+ end
69
+
70
+ describe "awz_constant" do
71
+ it "should look up an availability zone" do
72
+ awz_constant(:eu_west_1a).should == "eu-west-1a"
73
+ end
74
+ it "should look up an instance type" do
75
+ awz_constant(:m1_large).should == "m1.large"
76
+ end
77
+ it "should raise an error if the symbol is unknown" do
78
+ expect{awz_constant(:unknown_constant)}.to raise_error(Awsborn::UnknownConstantError)
79
+ end
80
+ end
81
+
82
+ end
data/spec/ec2_spec.rb CHANGED
@@ -1,12 +1,4 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe Awsborn::Ec2 do
4
- context ".endpoint_for_zone" do
5
- it "should have endpoints for zones in five regions" do
6
- Awsborn::Ec2.endpoint_for_zone(:eu_west_1a).should == 'https://eu-west-1.ec2.amazonaws.com'
7
- Awsborn::Ec2.endpoint_for_zone("eu_west_1b").should == 'https://eu-west-1.ec2.amazonaws.com'
8
- Awsborn::Ec2.endpoint_for_zone(:us_west_1b).should == 'https://us-west-1.ec2.amazonaws.com'
9
- Awsborn::Ec2.endpoint_for_zone(:us_east_1b).should == 'https://us-east-1.ec2.amazonaws.com'
10
- end
11
- end
12
4
  end
data/spec/elb_spec.rb ADDED
@@ -0,0 +1,256 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Awsborn::Elb do
4
+ before do
5
+ @mock_interface = mock(:elb_interface)
6
+ RightAws::ElbInterface.stub!(:new).and_return(@mock_interface)
7
+ Awsborn.stub!(:access_key_id).and_return('access_key_id')
8
+ Awsborn.stub!(:secret_access_key).and_return('secret_access_key')
9
+ end
10
+ describe "initialize" do
11
+ it "sets a proper endpoint" do
12
+ [:eu_west_1, 'eu-west-1', :eu_west_1a, "eu_west_1b"].each do |zone|
13
+ elb = Awsborn::Elb.new(:eu_west_1)
14
+ elb.region.should == 'eu-west-1'
15
+ elb.endpoint.should == 'https://eu-west-1.elasticloadbalancing.amazonaws.com'
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "connection" do
21
+ before do
22
+ @elb = Awsborn::Elb.new(:eu_west_1b)
23
+ end
24
+ it "setup a connection to a proper endpoint the first time" do
25
+ RightAws::ElbInterface.should_receive(:new).
26
+ with('access_key_id', 'secret_access_key', :logger => Awsborn.logger).
27
+ exactly(:once)
28
+ @elb.connection
29
+ @elb.connection
30
+ end
31
+ end
32
+
33
+ context "for a valid elb" do
34
+ before do
35
+ @elb = Awsborn::Elb.new(:eu_west_1b)
36
+ end
37
+
38
+ describe "describe_load_balancer" do
39
+ it "forwards to ElbInterface" do
40
+ @mock_interface.should_receive(:describe_load_balancers).with('some-name').and_return([:description])
41
+ @elb.describe_load_balancer('some-name').should == :description
42
+ end
43
+ end
44
+
45
+ describe "running?" do
46
+ it "returns true if load balancer is running" do
47
+ @mock_interface.should_receive(:describe_load_balancers).with('some-name').and_return([:description])
48
+ @elb.running?('some-name').should be_true
49
+ end
50
+ it "returns true if load balancer is not running" do
51
+ @mock_interface.should_receive(:describe_load_balancers).with('some-name').and_raise(RightAws::AwsError)
52
+ @elb.running?('some-name').should be_false
53
+ end
54
+ end
55
+
56
+ describe "dns_name" do
57
+ it "extracts name from description" do
58
+ @mock_interface.should_receive(:describe_load_balancers).with('some-name').and_return([{:dns_name => 'dns-name'}])
59
+ @elb.dns_name('some-name').should == 'dns-name'
60
+ end
61
+ end
62
+
63
+ describe "instances" do
64
+ it "extracts instances from description" do
65
+ @mock_interface.should_receive(:describe_load_balancers).with('some-name').and_return([{:instances => 'instances'}])
66
+ @elb.instances('some-name').should == 'instances'
67
+ end
68
+ end
69
+
70
+ describe "zones" do
71
+ it "extracts zones from description" do
72
+ @mock_interface.should_receive(:describe_load_balancers).with('some-name').and_return([{:availability_zones => 'zones'}])
73
+ @elb.zones('some-name').should == 'zones'
74
+ end
75
+ end
76
+
77
+ describe "create_load_balancer" do
78
+ it "forwards to ElbInterface with a temporary zone and no listeners" do
79
+ @mock_interface.should_receive(:create_load_balancer).with('some-name', ['eu-west-1a'], [])
80
+ @elb.create_load_balancer('some-name')
81
+ end
82
+ end
83
+
84
+ describe "set_load_balancer_listeners" do
85
+ it "sets listeners if none where set before" do
86
+ description = {
87
+ :listeners => []
88
+ }
89
+ new_listeners = [
90
+ { :protocol => :http, :load_balancer_port => 80, :instance_port => 80 },
91
+ ]
92
+ @mock_interface.should_receive(:describe_load_balancers).
93
+ with('some-name').
94
+ and_return([description])
95
+ @mock_interface.should_not_receive(:delete_load_balancer_listeners)
96
+ @mock_interface.should_receive(:create_load_balancer_listeners).with('some-name', new_listeners)
97
+ @elb.set_load_balancer_listeners('some-name', new_listeners)
98
+ end
99
+ it "updates listeners if some where set before" do
100
+ description = {
101
+ :listeners => [
102
+ { :protocol => :http, :load_balancer_port => 11, :instance_port => 11 },
103
+ { :protocol => :http, :load_balancer_port => 22, :instance_port => 22 },
104
+ { :protocol => :tcp, :load_balancer_port => 33, :instance_port => 33 }
105
+ ]
106
+ }
107
+ new_listeners = [
108
+ { :protocol => :http, :load_balancer_port => 80, :instance_port => 80 },
109
+ ]
110
+ @mock_interface.should_receive(:describe_load_balancers).
111
+ with('some-name').
112
+ and_return([description])
113
+ @mock_interface.should_receive(:delete_load_balancer_listeners).with('some-name', 11, 22, 33)
114
+ @mock_interface.should_receive(:create_load_balancer_listeners).with('some-name', new_listeners)
115
+ @elb.set_load_balancer_listeners('some-name', new_listeners)
116
+ end
117
+ end
118
+
119
+ describe "set_lb_cookie_policy" do
120
+ it "creates and sets sticky policy for each given port when the policy is missing" do
121
+ description = {
122
+ :listeners => [
123
+ { :protocol => :http, :load_balancer_port => 11, :instance_port => 11 },
124
+ { :protocol => :http, :load_balancer_port => 22, :instance_port => 22 },
125
+ { :protocol => :tcp, :load_balancer_port => 33, :instance_port => 33 }
126
+ ],
127
+ :lb_cookie_stickiness_policies => []
128
+ }
129
+ @mock_interface.should_receive(:describe_load_balancers).
130
+ with('some-name').
131
+ and_return([description])
132
+ @mock_interface.should_receive(:create_lb_cookie_stickiness_policy).
133
+ with('some-name', 'lb-some-name-300', 300)
134
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).
135
+ with('some-name', 11, 'lb-some-name-300')
136
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).
137
+ with('some-name', 22, 'lb-some-name-300')
138
+ @elb.set_lb_cookie_policy('some-name', [11, 22], 300)
139
+ end
140
+ it "does not create but sets sticky policy for each given port when the policy exists" do
141
+ description = {
142
+ :listeners => [
143
+ { :protocol => :http, :load_balancer_port => 11, :instance_port => 11 },
144
+ { :protocol => :http, :load_balancer_port => 22, :instance_port => 22 },
145
+ { :protocol => :tcp, :load_balancer_port => 33, :instance_port => 33 }
146
+ ],
147
+ :lb_cookie_stickiness_policies => [
148
+ { :policy_name => 'lb-some-name-300', :expiration_period => 42 },
149
+ ]
150
+ }
151
+ @mock_interface.should_receive(:describe_load_balancers).
152
+ with('some-name').
153
+ and_return([description])
154
+ @mock_interface.should_not_receive(:create_lb_cookie_stickiness_policy)
155
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).
156
+ with('some-name', 11, 'lb-some-name-300')
157
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).
158
+ with('some-name', 22, 'lb-some-name-300')
159
+ @elb.set_lb_cookie_policy('some-name', [11, 22], 300)
160
+ end
161
+ end
162
+
163
+ describe "set_app_cookie_policy" do
164
+ it "creates and sets sticky policy for each given port when the policy is missing" do
165
+ description = {
166
+ :listeners => [
167
+ { :protocol => :http, :load_balancer_port => 11, :instance_port => 11 },
168
+ { :protocol => :http, :load_balancer_port => 22, :instance_port => 22 },
169
+ { :protocol => :tcp, :load_balancer_port => 33, :instance_port => 33 }
170
+ ],
171
+ :app_cookie_stickiness_policies => []
172
+ }
173
+ @mock_interface.should_receive(:describe_load_balancers).
174
+ with('some-name').
175
+ and_return([description])
176
+ @mock_interface.should_receive(:create_app_cookie_stickiness_policy).
177
+ with('some-name', 'app-some-name--some-cookie', "_some_cookie")
178
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).
179
+ with('some-name', 11, 'app-some-name--some-cookie')
180
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).
181
+ with('some-name', 22, 'app-some-name--some-cookie')
182
+ @elb.set_app_cookie_policy('some-name', [11, 22], "_some_cookie")
183
+ end
184
+ it "does not create but sets sticky policy for each given port when the policy exists" do
185
+ description = {
186
+ :listeners => [
187
+ { :protocol => :http, :load_balancer_port => 11, :instance_port => 11 },
188
+ { :protocol => :http, :load_balancer_port => 22, :instance_port => 22 },
189
+ { :protocol => :tcp, :load_balancer_port => 33, :instance_port => 33 }
190
+ ],
191
+ :app_cookie_stickiness_policies => [
192
+ { :policy_name => 'app-some-name--some-cookie', :expiration_period => 42 },
193
+ ]
194
+ }
195
+ @mock_interface.should_receive(:describe_load_balancers).
196
+ with('some-name').
197
+ and_return([description])
198
+ @mock_interface.should_not_receive(:create_app_cookie_stickiness_policy)
199
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).
200
+ with('some-name', 11, 'app-some-name--some-cookie')
201
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).
202
+ with('some-name', 22, 'app-some-name--some-cookie')
203
+ @elb.set_app_cookie_policy('some-name', [11, 22], "_some_cookie")
204
+ end
205
+ end
206
+
207
+ describe "remove_all_cookie_policies" do
208
+ it "removes all policies from listeners" do
209
+ description = {
210
+ :listeners => [
211
+ { :protocol => :http, :load_balancer_port => 11, :instance_port => 11 },
212
+ { :protocol => :http, :load_balancer_port => 22, :instance_port => 22 },
213
+ { :protocol => :tcp, :load_balancer_port => 33, :instance_port => 33 }
214
+ ],
215
+ :app_cookie_stickiness_policies => []
216
+ }
217
+ @mock_interface.should_receive(:describe_load_balancers).
218
+ with('some-name').
219
+ and_return([description])
220
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).with('some-name', 11)
221
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).with('some-name', 22)
222
+ @mock_interface.should_receive(:set_load_balancer_policies_of_listener).with('some-name', 33)
223
+ @elb.remove_all_cookie_policies('some-name')
224
+ end
225
+ end
226
+
227
+ describe "register_instances" do
228
+ it "forwards to ElbInterface" do
229
+ @mock_interface.should_receive(:register_instances_with_load_balancer).with('some-name', 'i-00000001', 'i-00000002')
230
+ @elb.register_instances('some-name', ['i-00000001', 'i-00000002'])
231
+ end
232
+ end
233
+
234
+ describe "deregister_instances" do
235
+ it "forwards to ElbInterface" do
236
+ @mock_interface.should_receive(:deregister_instances_with_load_balancer).with('some-name', 'i-00000001', 'i-00000002')
237
+ @elb.deregister_instances('some-name', ['i-00000001', 'i-00000002'])
238
+ end
239
+ end
240
+
241
+ describe "enable_zones" do
242
+ it "forwards to ElbInterface" do
243
+ @mock_interface.should_receive(:enable_availability_zones_for_load_balancer).with('some-name', 'eu-west-1a', 'eu-west-1b')
244
+ @elb.enable_zones('some-name', ['eu-west-1a', 'eu-west-1b'])
245
+ end
246
+ end
247
+
248
+ describe "disable_zones" do
249
+ it "forwards to ElbInterface" do
250
+ @mock_interface.should_receive(:disable_availability_zones_for_load_balancer).with('some-name', 'eu-west-1a', 'eu-west-1b')
251
+ @elb.disable_zones('some-name', ['eu-west-1a', 'eu-west-1b'])
252
+ end
253
+ end
254
+ end
255
+ end
256
+
@@ -0,0 +1,288 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Awsborn::LoadBalancer do
4
+ before do
5
+ @mocked_elb = mock(:elb,
6
+ :running? => false,
7
+ :remove_all_cookie_policies => true,
8
+ :create_load_balancer => {})
9
+ @listener_fixture = [ { :protocol => :tcp, :load_balancer_port => 123, :instance_port => 123} ]
10
+ @cookies_fixture = [ { :ports => [123], :policy => :disabled } ]
11
+ Awsborn::Elb.stub!(:new).and_return(@mocked_elb)
12
+ end
13
+ describe "initialize" do
14
+ it "requires a valid region option" do
15
+ expect { Awsborn::LoadBalancer.new('some-name') }.to raise_error
16
+ expect { Awsborn::LoadBalancer.new('some-name', :region => :blabla) }.to raise_error
17
+ end
18
+ it "launches the load balancer if not running" do
19
+ @mocked_elb.should_receive(:running?).with('some-name').and_return(false)
20
+ @mocked_elb.should_receive(:create_load_balancer).with('some-name').and_return(nil)
21
+ @balancer = Awsborn::LoadBalancer.new(
22
+ 'some-name',
23
+ :region => :eu_west_1
24
+ )
25
+ end
26
+ it "does not launch the load balancer if running" do
27
+ @mocked_elb.should_receive(:running?).with('some-name').and_return(true)
28
+ @mocked_elb.should_not_receive(:create_load_balancer)
29
+ @balancer = Awsborn::LoadBalancer.new(
30
+ 'some-name',
31
+ :region => :eu_west_1
32
+ )
33
+ end
34
+ describe "sets all attributes properly" do
35
+ subject do
36
+ @balancer = Awsborn::LoadBalancer.new(
37
+ 'some-name',
38
+ :region => :eu_west_1a,
39
+ :only => [:server1, :server2],
40
+ :except => [:server2],
41
+ :listeners => @listener_fixture,
42
+ :sticky_cookies => @cookies_fixture
43
+ )
44
+ end
45
+ its(:name) { should == 'some-name' }
46
+ its(:region) { should == 'eu-west-1' }
47
+ its(:only) { should == [:server1, :server2] }
48
+ its(:except) { should == [:server2] }
49
+ its(:listeners) { should == @listener_fixture }
50
+ its(:sticky_cookies) { should == @cookies_fixture }
51
+ end
52
+ describe "sets proper default values" do
53
+ subject do
54
+ @balancer = Awsborn::LoadBalancer.new(
55
+ 'some-name',
56
+ :region => :eu_west_1
57
+ )
58
+ end
59
+ its(:only) { should == [] }
60
+ its(:except) { should == [] }
61
+ its(:listeners) { should == Awsborn::LoadBalancer::DEFAULT_LISTENERS }
62
+ its(:sticky_cookies) { should == [] }
63
+ end
64
+ end
65
+
66
+ describe "dns_name" do
67
+ it "delegates to elb" do
68
+ @mocked_elb.should_receive(:dns_name).with('some-name').and_return('dns-name')
69
+ @balancer = Awsborn::LoadBalancer.new(
70
+ 'some-name',
71
+ :region => :eu_west_1
72
+ ).dns_name.should == 'dns-name'
73
+ end
74
+ end
75
+
76
+
77
+ describe "instances" do
78
+ it "delegates to elb" do
79
+ @mocked_elb.should_receive(:instances).with('some-name').and_return('instances')
80
+ @balancer = Awsborn::LoadBalancer.new(
81
+ 'some-name',
82
+ :region => :eu_west_1
83
+ ).instances.should == 'instances'
84
+ end
85
+ end
86
+
87
+ describe "instances=" do
88
+ it "sets instances properly when the load balancer has no previous instances" do
89
+ @balancer = Awsborn::LoadBalancer.new(
90
+ 'some-name',
91
+ :region => :eu_west_1
92
+ )
93
+ @balancer.stub!(:instances).and_return([])
94
+ @mocked_elb.should_receive(:register_instances).with('some-name', ['i-00000001', 'i-00000002'])
95
+ @mocked_elb.should_not_receive(:deregister_instances)
96
+ @balancer.instances = ['i-00000001', 'i-00000002']
97
+ end
98
+ it "does nothing if the previous instances are the same as the ones to be set" do
99
+ @balancer = Awsborn::LoadBalancer.new(
100
+ 'some-name',
101
+ :region => :eu_west_1
102
+ )
103
+ @balancer.stub!(:instances).and_return(['i-00000001', 'i-00000002'])
104
+ @mocked_elb.should_not_receive(:register_instances)
105
+ @mocked_elb.should_not_receive(:deregister_instances)
106
+ @balancer.instances = ['i-00000001', 'i-00000002']
107
+ end
108
+ it "removes and adds instances accorind to previous and new state" do
109
+ @balancer = Awsborn::LoadBalancer.new(
110
+ 'some-name',
111
+ :region => :eu_west_1
112
+ )
113
+ @balancer.stub!(:instances).and_return(['i-00000001', 'i-00000002'])
114
+ @mocked_elb.should_receive(:register_instances).with('some-name', ['i-00000003'])
115
+ @mocked_elb.should_receive(:deregister_instances).with('some-name', ['i-00000001'])
116
+ @balancer.instances = ['i-00000002', 'i-00000003']
117
+ end
118
+ end
119
+
120
+ describe "zones" do
121
+ it "delegates to elb" do
122
+ @mocked_elb.should_receive(:zones).with('some-name').and_return('zones')
123
+ @balancer = Awsborn::LoadBalancer.new(
124
+ 'some-name',
125
+ :region => :eu_west_1
126
+ ).zones.should == 'zones'
127
+ end
128
+ end
129
+
130
+ describe "zones=" do
131
+ it "sets zones properly when the load balancer has no previous zones" do
132
+ @balancer = Awsborn::LoadBalancer.new(
133
+ 'some-name',
134
+ :region => :eu_west_1
135
+ )
136
+ @balancer.stub!(:zones).and_return([])
137
+ @mocked_elb.should_receive(:enable_zones).with('some-name', ['eu-west-1a', 'eu-west-1b'])
138
+ @mocked_elb.should_not_receive(:disable_zones)
139
+ @balancer.zones = ['eu-west-1a', 'eu-west-1b']
140
+ end
141
+ it "does nothing if the previous zones are the same as the ones to be set" do
142
+ @balancer = Awsborn::LoadBalancer.new(
143
+ 'some-name',
144
+ :region => :eu_west_1
145
+ )
146
+ @balancer.stub!(:zones).and_return(['eu-west-1a', 'eu-west-1b'])
147
+ @mocked_elb.should_not_receive(:enable_zones)
148
+ @mocked_elb.should_not_receive(:disable_zones)
149
+ @balancer.zones = ['eu-west-1a', 'eu-west-1b']
150
+ end
151
+ it "removes and adds zones accordind to previous and new state" do
152
+ @balancer = Awsborn::LoadBalancer.new(
153
+ 'some-name',
154
+ :region => :eu_west_1
155
+ )
156
+ @balancer.stub!(:zones).and_return(['eu-west-1a', 'eu-west-1b'])
157
+ @mocked_elb.should_receive(:enable_zones).with('some-name', ['eu-west-1c'])
158
+ @mocked_elb.should_receive(:disable_zones).with('some-name', ['eu-west-1a'])
159
+ @balancer.zones = ['eu-west-1b', 'eu-west-1c']
160
+ end
161
+ end
162
+
163
+ describe "description" do
164
+ it "delegates to elb" do
165
+ @mocked_elb.should_receive(:describe_load_balancer).with('some-name').and_return('description')
166
+ @balancer = Awsborn::LoadBalancer.new(
167
+ 'some-name',
168
+ :region => :eu_west_1
169
+ ).description.should == 'description'
170
+ end
171
+ end
172
+
173
+ describe "launch" do
174
+ it "delegates to elb" do
175
+ @mocked_elb.should_receive(:create_load_balancer).with('some-name')
176
+ @balancer = Awsborn::LoadBalancer.new(
177
+ 'some-name',
178
+ :region => :eu_west_1
179
+ ).launch
180
+ end
181
+ end
182
+
183
+ describe "update_listeners" do
184
+ it "delegates to elb" do
185
+ @mocked_elb.should_receive('set_load_balancer_listeners').with('some-name', @listener_fixture)
186
+ @balancer = Awsborn::LoadBalancer.new(
187
+ 'some-name',
188
+ :region => :eu_west_1,
189
+ :listeners => @listener_fixture
190
+ ).update_listeners
191
+ end
192
+ end
193
+
194
+ describe "update_sticky_cookies" do
195
+ it "sets proper policies" do
196
+ @balancer = Awsborn::LoadBalancer.new(
197
+ 'some-name',
198
+ :region => :eu_west_1,
199
+ :sticky_cookies => [
200
+ { :ports => [11,22], :policy => :disabled },
201
+ { :ports => [33], :policy => :app_generated, :cookie_name => 'some_cookie' },
202
+ { :ports => [44], :policy => :lb_generated, :expiration_period => 42 }
203
+ ]
204
+ )
205
+ @mocked_elb.should_receive(:remove_all_cookie_policies).with('some-name')
206
+ @mocked_elb.should_receive(:set_app_sticky_cookie).with('some-name', [33], 'some_cookie')
207
+ @mocked_elb.should_receive(:set_lb_sticky_cookie).with('some-name', [44], 42)
208
+
209
+ @balancer.update_sticky_cookies
210
+ end
211
+
212
+ it "raises an error if a policy is missing a ports option" do
213
+ @balancer = Awsborn::LoadBalancer.new(
214
+ 'some-name',
215
+ :region => :eu_west_1,
216
+ :sticky_cookies => [
217
+ { :policy => :disabled },
218
+ ]
219
+ )
220
+ expect { @balancer.update_sticky_cookies }.to raise_error
221
+ end
222
+ it "raises an error if an app sticky policy is missing a cookie name" do
223
+ @balancer = Awsborn::LoadBalancer.new(
224
+ 'some-name',
225
+ :region => :eu_west_1,
226
+ :sticky_cookies => [
227
+ { :ports => [33], :policy => :app_generated },
228
+ ]
229
+ )
230
+ expect { @balancer.update_sticky_cookies }.to raise_error
231
+ end
232
+ it "raises an error if an lb sticky policy is missing an expiration period" do
233
+ @balancer = Awsborn::LoadBalancer.new(
234
+ 'some-name',
235
+ :region => :eu_west_1,
236
+ :sticky_cookies => [
237
+ { :ports => [44], :policy => :lb_generated }
238
+ ]
239
+ )
240
+ expect { @balancer.update_sticky_cookies }.to raise_error
241
+ end
242
+ end
243
+
244
+ describe "update_with" do
245
+ before do
246
+ @balancer = Awsborn::LoadBalancer.new(
247
+ 'some-name',
248
+ :region => :eu_west_1a,
249
+ :listeners => @listener_fixture,
250
+ :sticky_cookies => @cookies_fixture
251
+ )
252
+ @new_servers = [
253
+ mock(:server1, :name => :server1, :instance_id => 'i-00000001', :zone => :eu_west_1a),
254
+ mock(:server1, :name => :server2, :instance_id => 'i-00000002', :zone => :eu_west_1b)
255
+ ]
256
+ end
257
+ it "sets new instances, sets new zones, updates listeners and updates sticky cookies" do
258
+ @balancer.should_receive(:instances=).with(['i-00000001', 'i-00000002'])
259
+ @balancer.should_receive(:zones=).with(['eu-west-1a', 'eu-west-1b'])
260
+ @balancer.should_receive(:update_listeners)
261
+ @balancer.should_receive(:update_sticky_cookies)
262
+ @balancer.should_receive(:description).and_return('description')
263
+ @balancer.update_with(@new_servers).should == 'description'
264
+ end
265
+ it "takes into account the :only option" do
266
+ @balancer.only = [:server1]
267
+
268
+ @balancer.should_receive(:instances=).with(['i-00000001'])
269
+ @balancer.should_receive(:zones=).with(['eu-west-1a'])
270
+ @balancer.should_receive(:update_listeners)
271
+ @balancer.should_receive(:update_sticky_cookies)
272
+ @balancer.should_receive(:description).and_return('description')
273
+ @balancer.update_with(@new_servers).should == 'description'
274
+ end
275
+ it "takes into account the :except option" do
276
+ @balancer.except = [:server1]
277
+
278
+ @balancer.should_receive(:instances=).with(['i-00000002'])
279
+ @balancer.should_receive(:zones=).with(['eu-west-1b'])
280
+ @balancer.should_receive(:update_listeners)
281
+ @balancer.should_receive(:update_sticky_cookies)
282
+ @balancer.should_receive(:description).and_return('description')
283
+ @balancer.update_with(@new_servers).should == 'description'
284
+ end
285
+ end
286
+
287
+ end
288
+