awsborn 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+