awsborn 0.8.1 → 0.8.2

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.
data/README.mdown CHANGED
@@ -113,6 +113,9 @@ Mandatory keys for load_balancer:
113
113
 
114
114
  Optional keys for load_balancer:
115
115
 
116
+ * `:dns_alias` -- a domain name to be tied to the load balancer in Route 53.
117
+ May be a simple name (`www`) in which case the cluster domain will be added,
118
+ or a full domain name.
116
119
  * `:only` -- a list of server names to which the load balancer is
117
120
  restricted.
118
121
  * `:except` -- a list of servers that the load balancer should ignore.
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ begin
10
10
  gem.email = "david@icehouse.se"
11
11
  gem.homepage = "http://github.com/icehouse/awsborn"
12
12
  gem.authors = ["David Vrensk", "Jean-Louis Giordano"]
13
- gem.add_dependency "right_aws", ">= 2.1.0"
13
+ gem.add_dependency "icehouse-right_aws", ">= 2.2.0"
14
14
  gem.add_dependency "json_pure", ">= 1.2.3"
15
15
  gem.add_dependency "rake"
16
16
  gem.add_development_dependency "rspec", ">= 2.6.0"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.1
1
+ 0.8.2
data/awsborn.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{awsborn}
8
- s.version = "0.8.1"
8
+ s.version = "0.8.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["David Vrensk", "Jean-Louis Giordano"]
12
- s.date = %q{2011-08-16}
12
+ s.date = %q{2011-08-23}
13
13
  s.description = %q{Awsborn lets you define and launch a server cluster on Amazon EC2.}
14
14
  s.email = %q{david@icehouse.se}
15
15
  s.extra_rdoc_files = [
@@ -37,12 +37,15 @@ Gem::Specification.new do |s|
37
37
  "lib/awsborn/known_hosts_updater.rb",
38
38
  "lib/awsborn/load_balancer.rb",
39
39
  "lib/awsborn/rake.rb",
40
+ "lib/awsborn/route53.rb",
40
41
  "lib/awsborn/server.rb",
41
42
  "lib/awsborn/server_cluster.rb",
42
43
  "spec/aws_constants_spec.rb",
43
44
  "spec/ec2_spec.rb",
44
45
  "spec/elb_spec.rb",
45
46
  "spec/load_balancer_spec.rb",
47
+ "spec/route53_spec.rb",
48
+ "spec/server_cluster_spec.rb",
46
49
  "spec/server_spec.rb",
47
50
  "spec/spec.opts",
48
51
  "spec/spec_helper.rb"
@@ -57,20 +60,20 @@ Gem::Specification.new do |s|
57
60
  s.specification_version = 3
58
61
 
59
62
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
60
- s.add_runtime_dependency(%q<right_aws>, [">= 2.1.0"])
63
+ s.add_runtime_dependency(%q<icehouse-right_aws>, [">= 2.2.0"])
61
64
  s.add_runtime_dependency(%q<json_pure>, [">= 1.2.3"])
62
65
  s.add_runtime_dependency(%q<rake>, [">= 0"])
63
66
  s.add_development_dependency(%q<rspec>, [">= 2.6.0"])
64
67
  s.add_development_dependency(%q<webmock>, [">= 1.3.0"])
65
68
  else
66
- s.add_dependency(%q<right_aws>, [">= 2.1.0"])
69
+ s.add_dependency(%q<icehouse-right_aws>, [">= 2.2.0"])
67
70
  s.add_dependency(%q<json_pure>, [">= 1.2.3"])
68
71
  s.add_dependency(%q<rake>, [">= 0"])
69
72
  s.add_dependency(%q<rspec>, [">= 2.6.0"])
70
73
  s.add_dependency(%q<webmock>, [">= 1.3.0"])
71
74
  end
72
75
  else
73
- s.add_dependency(%q<right_aws>, [">= 2.1.0"])
76
+ s.add_dependency(%q<icehouse-right_aws>, [">= 2.2.0"])
74
77
  s.add_dependency(%q<json_pure>, [">= 1.2.3"])
75
78
  s.add_dependency(%q<rake>, [">= 0"])
76
79
  s.add_dependency(%q<rspec>, [">= 2.6.0"])
data/lib/awsborn/elb.rb CHANGED
@@ -50,6 +50,10 @@ module Awsborn
50
50
  describe_load_balancer(balancer_name)[:availability_zones]
51
51
  end
52
52
 
53
+ def canonical_hosted_zone_name_id (balancer_name)
54
+ describe_load_balancer(balancer_name)[:canonical_hosted_zone_name_id]
55
+ end
56
+
53
57
  def create_load_balancer (balancer_name)
54
58
  logger.debug "Creating load balancer #{balancer_name}"
55
59
  connection.create_load_balancer(balancer_name, [@region+'a'], [])
@@ -2,7 +2,7 @@ module Awsborn
2
2
  class LoadBalancer
3
3
 
4
4
  include Awsborn::AwsConstants
5
- attr_accessor :name, :only, :except, :region, :listeners, :sticky_cookies, :health_check_config
5
+ attr_accessor :name, :only, :except, :region, :listeners, :sticky_cookies, :health_check_config, :dns_alias
6
6
 
7
7
  DEFAULT_LISTENERS = [ { :protocol => :http, :load_balancer_port => 80, :instance_port => 80} ]
8
8
  DEFAULT_HEALTH_CONFIG = {
@@ -12,6 +12,7 @@ module Awsborn
12
12
  :timeout => 5,
13
13
  :interval => 30
14
14
  }
15
+
15
16
  def initialize (name, options={})
16
17
  @name = name
17
18
  @only = options[:only] || []
@@ -20,13 +21,14 @@ module Awsborn
20
21
  @listeners = options[:listeners] || DEFAULT_LISTENERS
21
22
  @sticky_cookies = options[:sticky_cookies] || []
22
23
  @health_check_config = DEFAULT_HEALTH_CONFIG.merge(options[:health_check] || {})
24
+ @dns_alias = options[:dns_alias]
23
25
  end
24
26
 
25
27
  def elb
26
28
  @elb ||= Elb.new(@region)
27
29
  end
28
30
 
29
- def dns_name
31
+ def aws_dns_name
30
32
  elb.dns_name(@name)
31
33
  end
32
34
 
@@ -34,11 +36,14 @@ module Awsborn
34
36
  elb.instances(@name)
35
37
  end
36
38
 
39
+ def canonical_hosted_zone_name_id
40
+ elb.canonical_hosted_zone_name_id(@name)
41
+ end
42
+
37
43
  def instances= (new_instances)
38
44
  previous_instances = self.instances
39
45
  register_instances(new_instances - previous_instances)
40
46
  deregister_instances(previous_instances - new_instances)
41
- self.instances
42
47
  end
43
48
 
44
49
  def zones
@@ -49,7 +54,6 @@ module Awsborn
49
54
  previous_zones = self.zones
50
55
  enable_zones(new_zones - previous_zones)
51
56
  disable_zones(previous_zones - new_zones)
52
- self.zones
53
57
  end
54
58
 
55
59
  def description
@@ -94,27 +98,58 @@ module Awsborn
94
98
  elb.configure_health_check(@name, @health_check_config)
95
99
  end
96
100
 
97
- def update_with (new_servers)
101
+ def launch_or_update (running_servers)
98
102
  launch unless running?
99
103
 
100
- servers_to_be_balanced = new_servers
101
- servers_to_be_balanced =
102
- servers_to_be_balanced.select{|s| @only.include?(s.name)} unless @only.empty?
103
- servers_to_be_balanced =
104
- servers_to_be_balanced.reject{|s| @except.include?(s.name)} unless @except.empty?
104
+ set_instances_to_selected(running_servers)
105
+ update_settings
105
106
 
106
- self.instances = servers_to_be_balanced.map{|s| s.instance_id }
107
- self.zones = servers_to_be_balanced.map{|s| symbol_to_aws_zone(s.zone) }.uniq
107
+ configure_dns if @dns_alias
108
+ end
108
109
 
109
- update_listeners
110
- update_sticky_cookies
111
- update_health_config
110
+ def configure_dns
111
+ route53.create_zone @dns_alias unless route53.zone_exists?(@dns_alias)
112
+ case route53.alias_target(@dns_alias)
113
+ when aws_dns_name
114
+ # It is already good
115
+ when nil
116
+ route53.add_alias_record(:alias => @dns_alias, :lb_fqdn => aws_dns_name, :lb_zone => canonical_hosted_zone_name_id)
117
+ else
118
+ route53.remove_alias_records(@dns_alias)
119
+ route53.add_alias_record(:alias => @dns_alias, :lb_fqdn => aws_dns_name, :lb_zone => canonical_hosted_zone_name_id)
120
+ end
121
+ end
112
122
 
113
- self.description
123
+ def route53
124
+ @route53 ||= Route53.new
125
+ end
126
+
127
+ def dns_info
128
+ if dns_alias
129
+ route53.zone_for(dns_alias)
130
+ end
114
131
  end
115
132
 
116
133
  protected
117
134
 
135
+ def set_instances_to_selected (running_servers)
136
+ servers_to_be_balanced = select_servers(running_servers)
137
+ self.instances = servers_to_be_balanced.map {|s| s.instance_id }
138
+ self.zones = servers_to_be_balanced.map {|s| symbol_to_aws_zone(s.zone) }.uniq
139
+ end
140
+
141
+ def select_servers (servers)
142
+ servers = servers.select {|s| @only.include?(s.name)} unless @only.empty?
143
+ servers = servers.reject {|s| @except.include?(s.name)} unless @except.empty?
144
+ servers
145
+ end
146
+
147
+ def update_settings
148
+ update_listeners
149
+ update_sticky_cookies
150
+ update_health_config
151
+ end
152
+
118
153
  def set_disabled_cookie_policy(ports)
119
154
  # Do nothing
120
155
  end
data/lib/awsborn/rake.rb CHANGED
@@ -26,7 +26,19 @@ module Awsborn
26
26
 
27
27
  desc "Start all servers (or host=name1,name2) but don't run chef."
28
28
  task :start do |t,args|
29
- cluster(args).launch get_hosts(args)
29
+ c = cluster(args)
30
+ c.launch get_hosts(args)
31
+ info = c.load_balancer_info
32
+ print_required_dns_setting(info) if info
33
+ end
34
+
35
+ def print_required_dns_setting (info)
36
+ puts "Make sure those NS records are present in your DNS settings:"
37
+ puts(info.map do |dns_entry|
38
+ dns_entry[:name_servers].map do |ns|
39
+ "#{dns_entry[:name]}\tIN\tNS\t#{ns}."
40
+ end
41
+ end.join("\n"))
30
42
  end
31
43
 
32
44
  desc "Update .ssh/known_hosts with data from all servers (or host=host1,host2)"
@@ -132,4 +144,4 @@ EOH
132
144
 
133
145
  end
134
146
  end
135
- end
147
+ end
@@ -0,0 +1,70 @@
1
+ module Awsborn
2
+ class Route53
3
+ extend Forwardable
4
+ def_delegators :Awsborn, :logger
5
+ include Awsborn::AwsConstants
6
+ attr_reader :connection
7
+
8
+ def connection
9
+ unless @connection
10
+ @connection = RightAws::Route53Interface.new(Awsborn.access_key_id, Awsborn.secret_access_key, :logger => Awsborn.logger)
11
+ end
12
+ @connection
13
+ end
14
+
15
+ def initialize (zone = nil)
16
+ end
17
+
18
+ def zone_exists? (name)
19
+ !! zone_overview_for(name)
20
+ end
21
+
22
+ def zone_for (name)
23
+ zone_id = zone_id_for(name)
24
+ connection.get_hosted_zone(zone_id) if zone_id
25
+ end
26
+
27
+ def zone_id_for (name)
28
+ overview = zone_overview_for(name)
29
+ overview[:aws_id] if overview
30
+ end
31
+
32
+ def create_zone (name)
33
+ connection.create_hosted_zone({:name => with_final_dot(name), :config => {:comment => ''}})
34
+ end
35
+
36
+ def alias_target (name)
37
+ name = with_final_dot(name)
38
+ zone = zone_id_for(name)
39
+ alias_record = connection.list_resource_record_sets(zone).detect { |rr| rr[:name] == name && rr[:alias_target] }
40
+ alias_record && alias_record[:alias_target]
41
+ end
42
+
43
+ def add_alias_record (options)
44
+ name = with_final_dot(options[:alias])
45
+ zone = zone_id_for(name)
46
+ alias_target = { :hosted_zone_id => options[:lb_zone], :dns_name => options[:lb_fqdn] }
47
+ alias_record = { :name => options[:alias], :type => 'A', :alias_target => alias_target }
48
+ connection.create_resource_record_sets(zone, [alias_record])
49
+ end
50
+
51
+ def remove_alias_records (name)
52
+ name = with_final_dot(name)
53
+ zone = zone_id_for(name)
54
+ alias_records = connection.list_resource_record_sets(zone).select { |rr| rr[:name] == name && rr[:alias_target] }
55
+ connection.delete_resource_record_sets(zone, alias_records)
56
+ end
57
+
58
+ private
59
+
60
+ def zone_overview_for (name)
61
+ name = with_final_dot(name)
62
+ zones = connection.list_hosted_zones
63
+ zone = zones.detect { |zone| zone[:name] == name }
64
+ end
65
+
66
+ def with_final_dot (name)
67
+ name =~ /\.$/ ? name : "#{name}."
68
+ end
69
+ end
70
+ end
@@ -2,7 +2,7 @@ module Awsborn
2
2
  class ServerCluster
3
3
  include Enumerable
4
4
 
5
- attr_accessor :name
5
+ attr_accessor :name, :load_balancers
6
6
 
7
7
  def self.build (klass, name, &block)
8
8
  cluster = new(klass, name)
@@ -44,6 +44,7 @@ module Awsborn
44
44
  end
45
45
 
46
46
  def load_balancer (name, options={})
47
+ options = add_domain_to_dns_alias(options)
47
48
  @load_balancers << Awsborn::LoadBalancer.new(name, options)
48
49
  end
49
50
 
@@ -73,10 +74,17 @@ module Awsborn
73
74
 
74
75
  def update_load_balancing(running)
75
76
  @load_balancers.each do |lb|
76
- lb.update_with(running).inspect
77
+ lb.launch_or_update(running)
77
78
  end
78
79
  end
79
80
 
81
+ def load_balancer_info
82
+ info = load_balancers.map do |lb|
83
+ lb.dns_info
84
+ end.compact
85
+ info.empty? ? nil : info
86
+ end
87
+
80
88
  def generate_key_pair (instances)
81
89
  @key_pair = instances.first.ec2.generate_key_pair
82
90
  end
@@ -96,9 +104,15 @@ module Awsborn
96
104
  protected
97
105
 
98
106
  def add_domain_to_ip (hash)
99
- if @domain && hash.has_key?(:ip) && ! hash[:ip].include?('.')
100
- ip = [hash[:ip], @domain].join('.')
101
- hash.merge(:ip => ip)
107
+ add_domain_to_key(:ip, hash)
108
+ end
109
+ def add_domain_to_dns_alias (hash)
110
+ add_domain_to_key(:dns_alias, hash)
111
+ end
112
+ def add_domain_to_key (key, hash)
113
+ if @domain && hash.has_key?(key) && ! hash[key].include?('.')
114
+ expanded = [hash[key], @domain].join('.')
115
+ hash.merge(key => expanded)
102
116
  else
103
117
  hash
104
118
  end
data/spec/elb_spec.rb CHANGED
@@ -74,6 +74,13 @@ describe Awsborn::Elb do
74
74
  end
75
75
  end
76
76
 
77
+ describe "canonical_hosted_zone_name_id" do
78
+ it "extracts zone id from description" do
79
+ @mock_interface.should_receive(:describe_load_balancers).with('some-name').and_return([{:canonical_hosted_zone_name_id => 'Z000'}])
80
+ @elb.canonical_hosted_zone_name_id('some-name').should == 'Z000'
81
+ end
82
+ end
83
+
77
84
  describe "create_load_balancer" do
78
85
  it "forwards to ElbInterface with a temporary zone and no listeners" do
79
86
  @mock_interface.should_receive(:create_load_balancer).with('some-name', ['eu-west-1a'], [])
@@ -12,7 +12,17 @@ describe Awsborn::LoadBalancer do
12
12
  :enable_zones => true,
13
13
  :set_load_balancer_listeners => true,
14
14
  :describe_load_balancer => "description",
15
- :configure_health_check => true)
15
+ :dns_name => 'asdf',
16
+ :configure_health_check => true)
17
+ Awsborn::Elb.stub!(:new).and_return(@mocked_elb)
18
+
19
+ @mocked_route53 = mock(:route53,
20
+ :zone_exists? => true,
21
+ :add_alias_record => true,
22
+ :alias_target => 'some-name-0001.lb.amz.com'
23
+ )
24
+ Awsborn::Route53.stub!(:new).and_return(@mocked_route53)
25
+
16
26
  @listener_fixture = [ { :protocol => :tcp, :load_balancer_port => 123, :instance_port => 123} ]
17
27
  @cookies_fixture = [ { :ports => [123], :policy => :disabled } ]
18
28
  @health_check_fixture = {
@@ -22,8 +32,8 @@ describe Awsborn::LoadBalancer do
22
32
  :timeout => 6,
23
33
  :interval => 31
24
34
  }
25
- Awsborn::Elb.stub!(:new).and_return(@mocked_elb)
26
35
  end
36
+
27
37
  describe "initialize" do
28
38
  it "requires a valid region option" do
29
39
  expect { Awsborn::LoadBalancer.new('some-name') }.to raise_error
@@ -33,7 +43,8 @@ describe Awsborn::LoadBalancer do
33
43
  subject do
34
44
  @balancer = Awsborn::LoadBalancer.new(
35
45
  'some-name',
36
- :region => :eu_west_1a,
46
+ :dns_alias => 'www.example.net',
47
+ :region => :eu_west_1,
37
48
  :only => [:server1, :server2],
38
49
  :except => [:server2],
39
50
  :listeners => @listener_fixture,
@@ -42,6 +53,7 @@ describe Awsborn::LoadBalancer do
42
53
  )
43
54
  end
44
55
  its(:name) { should == 'some-name' }
56
+ its(:dns_alias) { should == 'www.example.net' }
45
57
  its(:region) { should == 'eu-west-1' }
46
58
  its(:only) { should == [:server1, :server2] }
47
59
  its(:except) { should == [:server2] }
@@ -76,17 +88,16 @@ describe Awsborn::LoadBalancer do
76
88
  end
77
89
  end
78
90
 
79
- describe "dns_name" do
91
+ describe "aws_dns_name" do
80
92
  it "delegates to elb" do
81
93
  @mocked_elb.should_receive(:dns_name).with('some-name').and_return('dns-name')
82
94
  @balancer = Awsborn::LoadBalancer.new(
83
95
  'some-name',
84
96
  :region => :eu_west_1
85
- ).dns_name.should == 'dns-name'
97
+ ).aws_dns_name.should == 'dns-name'
86
98
  end
87
99
  end
88
100
 
89
-
90
101
  describe "instances" do
91
102
  it "delegates to elb" do
92
103
  @mocked_elb.should_receive(:instances).with('some-name').and_return('instances')
@@ -275,7 +286,7 @@ describe Awsborn::LoadBalancer do
275
286
  end
276
287
  end
277
288
 
278
- describe "update_with" do
289
+ describe "launch_or_update" do
279
290
  before do
280
291
  @balancer = Awsborn::LoadBalancer.new(
281
292
  'some-name',
@@ -291,12 +302,12 @@ describe Awsborn::LoadBalancer do
291
302
  it "launches the load balancer if not running" do
292
303
  @mocked_elb.should_receive(:running?).with('some-name').and_return(false)
293
304
  @mocked_elb.should_receive(:create_load_balancer).with('some-name').and_return(nil)
294
- @balancer.update_with(@new_servers)
305
+ @balancer.launch_or_update(@new_servers)
295
306
  end
296
307
  it "does not launch the load balancer if running" do
297
308
  @mocked_elb.should_receive(:running?).with('some-name').and_return(true)
298
309
  @mocked_elb.should_not_receive(:create_load_balancer)
299
- @balancer.update_with(@new_servers)
310
+ @balancer.launch_or_update(@new_servers)
300
311
  end
301
312
  it "sets instances and new zones and updates listeners, sticky cookies and health config" do
302
313
  @balancer.should_receive(:instances=).with(['i-00000001', 'i-00000002'])
@@ -304,8 +315,7 @@ describe Awsborn::LoadBalancer do
304
315
  @balancer.should_receive(:update_listeners)
305
316
  @balancer.should_receive(:update_sticky_cookies)
306
317
  @balancer.should_receive(:update_health_config)
307
- @balancer.should_receive(:description).and_return('description')
308
- @balancer.update_with(@new_servers).should == 'description'
318
+ @balancer.launch_or_update(@new_servers)
309
319
  end
310
320
  it "takes into account the :only option" do
311
321
  @balancer.only = [:server1]
@@ -315,8 +325,7 @@ describe Awsborn::LoadBalancer do
315
325
  @balancer.should_receive(:update_listeners)
316
326
  @balancer.should_receive(:update_sticky_cookies)
317
327
  @balancer.should_receive(:update_health_config)
318
- @balancer.should_receive(:description).and_return('description')
319
- @balancer.update_with(@new_servers).should == 'description'
328
+ @balancer.launch_or_update(@new_servers)
320
329
  end
321
330
  it "takes into account the :except option" do
322
331
  @balancer.except = [:server1]
@@ -327,9 +336,68 @@ describe Awsborn::LoadBalancer do
327
336
  @balancer.should_receive(:update_sticky_cookies)
328
337
  @balancer.should_receive(:update_health_config)
329
338
  @balancer.should_receive(:description).and_return('description')
330
- @balancer.update_with(@new_servers).should == 'description'
339
+ @balancer.launch_or_update(@new_servers)
340
+ @balancer.description.should == 'description'
341
+ end
342
+ it "configures dns" do
343
+ @balancer.dns_alias = 'www.example.net'
344
+ @balancer.should_receive(:configure_dns)
345
+ @balancer.launch_or_update(@new_servers)
331
346
  end
332
347
  end
333
348
 
334
- end
349
+ describe "configure_dns" do
350
+ before do
351
+ @balancer = Awsborn::LoadBalancer.new('some-name', :region => :eu_west_1, :dns_alias => 'www.example.net')
352
+ @balancer.stub!(:aws_dns_name).and_return('some-name-0001.lb.amz.com')
353
+ @balancer.stub!(:canonical_hosted_zone_name_id).and_return('Z0000000000')
354
+ end
355
+
356
+ it "creates the zone if it does not exist" do
357
+ @mocked_route53.should_receive(:create_zone).with('www.example.net')
358
+ @mocked_route53.should_receive(:zone_exists?).with('www.example.net').and_return(false)
359
+ @balancer.configure_dns
360
+ end
361
+
362
+ it "doesn't create the zone if it already exists" do
363
+ @mocked_route53.should_not_receive(:create_zone)
364
+ @mocked_route53.should_receive(:zone_exists?).with('www.example.net').and_return(true)
365
+ @balancer.configure_dns
366
+ end
367
+
368
+ it "adds the load balancer name as an Alias record" do
369
+ @mocked_route53.should_receive(:alias_target).with('www.example.net').and_return(nil)
370
+ @mocked_route53.should_receive(:add_alias_record).with(:alias => 'www.example.net',
371
+ :lb_fqdn => 'some-name-0001.lb.amz.com', :lb_zone => 'Z0000000000')
372
+ @balancer.configure_dns
373
+ end
374
+
375
+ it "removes an outdated alias record" do
376
+ @mocked_route53.should_receive(:alias_target).with('www.example.net').and_return('old-name-1.lb.amz.com')
377
+ @mocked_route53.should_receive(:remove_alias_records).with('www.example.net')
378
+ @mocked_route53.should_receive(:add_alias_record).with(:alias => 'www.example.net',
379
+ :lb_fqdn => 'some-name-0001.lb.amz.com', :lb_zone => 'Z0000000000')
380
+ @balancer.configure_dns
381
+ end
382
+
383
+ it "doesn't touch the records if they are OK" do
384
+ @mocked_route53.should_not_receive(:add_alias_record)
385
+ @mocked_route53.should_not_receive(:remove_alias_records)
386
+ @balancer.configure_dns
387
+ end
388
+ end
335
389
 
390
+ describe "dns_info" do
391
+ it "forwards to route53 if dns_alias is present" do
392
+ @balancer = Awsborn::LoadBalancer.new(
393
+ 'some-name',
394
+ :region => :eu_west_1a,
395
+ :dns_alias => 'my-awesome-site.example.com.'
396
+ )
397
+ @mocked_route53.should_receive(:zone_for).
398
+ with('my-awesome-site.example.com.').
399
+ and_return('pasta banana')
400
+ @balancer.dns_info.should == 'pasta banana'
401
+ end
402
+ end
403
+ end
@@ -0,0 +1,145 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Awsborn::Route53 do
4
+ before do
5
+ @mock_interface = mock(:route53_interface)
6
+ RightAws::Route53Interface.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
+
11
+ describe "connection" do
12
+ before do
13
+ @r53 = Awsborn::Route53.new
14
+ end
15
+ it "setup a connection the first time" do
16
+ RightAws::Route53Interface.should_receive(:new).
17
+ with('access_key_id', 'secret_access_key', :logger => Awsborn.logger).
18
+ exactly(:once)
19
+ @r53.connection
20
+ @r53.connection
21
+ end
22
+ end
23
+
24
+ context "for a valid r53" do
25
+ before do
26
+ @r53 = Awsborn::Route53.new(:eu_west_1b)
27
+ @zone_list_fixture = [
28
+ {
29
+ :aws_id=>"/hostedzone/Z1111111111111",
30
+ :caller_reference=>"1295422234-657482-hfkeo-JFKid-Ldfle-Sdrty",
31
+ :config=>{:comment=>"My test site!"},
32
+ :name=>"my-awesome-site.com."
33
+ },
34
+ {
35
+ :aws_id=>"/hostedzone/Z2222222222222",
36
+ :caller_reference=>"1234567890",
37
+ :config=>{:comment=>"My second test site!"},
38
+ :name=>"my-other-awesome-site.com."
39
+ }
40
+ ]
41
+ @zone_detail_fixture = {
42
+ :config=>{:comment=>"My test site!"},
43
+ :aws_id=>"/hostedzone/Z1111111111111",
44
+ :caller_reference=>"1295422234-657482-hfkeo-JFKid-Ldfle-Sdrty",
45
+ :name_servers=>
46
+ [ "ns-794.awsdns-35.net",
47
+ "ns-459.awsdns-57.com",
48
+ "ns-1537.awsdns-00.co.uk",
49
+ "ns-1165.awsdns-17.org"],
50
+ :name=>"my-awesome-site.com."}
51
+ end
52
+
53
+ describe "zone_exists?" do
54
+ before do
55
+ @mock_interface.stub!(:list_hosted_zones).and_return(@zone_list_fixture)
56
+ end
57
+ it "checks the result from Route53Interface" do
58
+ @r53.zone_exists?('my-awesome-site.com.').should == true
59
+ @r53.zone_exists?('my-awesome-site.com').should == true
60
+ @r53.zone_exists?('horrible.com').should == false
61
+ end
62
+ end
63
+
64
+ describe "zone_for" do
65
+ before do
66
+ @mock_interface.stub!(:list_hosted_zones).and_return(@zone_list_fixture)
67
+ end
68
+ it "retrieves zone description from Route53Interface if a zone matches the given name" do
69
+ @mock_interface.should_receive(:get_hosted_zone).
70
+ with("/hostedzone/Z1111111111111").
71
+ and_return(@zone_detail_fixture)
72
+ @r53.zone_for('my-awesome-site.com.').should == @zone_detail_fixture
73
+ end
74
+ it "retrieves zone description from Route53Interface even for a name without ending dot" do
75
+ @mock_interface.should_receive(:get_hosted_zone).
76
+ with("/hostedzone/Z1111111111111").
77
+ and_return(@zone_detail_fixture)
78
+ @r53.zone_for('my-awesome-site.com').should == @zone_detail_fixture
79
+ end
80
+ it "returns nil if no zone match the given name" do
81
+ @mock_interface.should_not_receive(:get_hosted_zone)
82
+ @r53.zone_for('horrible.com').should be_nil
83
+ end
84
+ end
85
+
86
+ describe "zone_id_for" do
87
+ before do
88
+ @mock_interface.stub!(:list_hosted_zones).and_return(@zone_list_fixture)
89
+ end
90
+ it "checks the result from Route53Interface" do
91
+ @r53.zone_id_for('my-awesome-site.com.').should == "/hostedzone/Z1111111111111"
92
+ @r53.zone_id_for('my-awesome-site.com').should == "/hostedzone/Z1111111111111"
93
+ @r53.zone_id_for('horrible.com').should be_nil
94
+ end
95
+
96
+ end
97
+
98
+ describe "create_zone" do
99
+ it "delegates to Route53Interface" do
100
+ @mock_interface.should_receive(:create_hosted_zone).with({:name => 'example.net.', :config => {:comment => ''}})
101
+ @r53.create_zone 'example.net'
102
+ end
103
+ end
104
+
105
+ describe "alias_target" do
106
+ it "delegates cleverly to Route53Interface" do
107
+ @mock_interface.should_receive(:list_hosted_zones).and_return(@zone_list_fixture)
108
+ alias_target = { :hosted_zone_id => 'Z2222222222', :dns_name => 'example-1111111111.us-east-1.elb.amazonaws.com.' }
109
+ alias_record = { :name => 'example.net.', :type => 'A', :alias_target => alias_target }
110
+ @mock_interface.should_receive(:list_resource_record_sets).with(/Z111111111111/).and_return([alias_record])
111
+
112
+ @r53.alias_target('my-awesome-site.com')
113
+ end
114
+ end
115
+
116
+ describe "add_alias_record" do
117
+ it "delegates to Route53Interface" do
118
+ zones = [{:aws_id=>"/hostedzone/Z111111111111", :name=>"example.net."}]
119
+ @mock_interface.stub!(:list_hosted_zones).and_return(zones)
120
+
121
+ alias_target = { :hosted_zone_id => 'Z2222222222', :dns_name => 'example-1111111111.us-east-1.elb.amazonaws.com.' }
122
+ alias_record = { :name => 'example.net.', :type => 'A', :alias_target => alias_target }
123
+
124
+ # .dup since it will get :action => :create
125
+ @mock_interface.should_receive(:create_resource_record_sets).with(/Z111111111111/, [alias_record.dup])
126
+
127
+ @r53.add_alias_record(:alias => 'example.net.', :lb_fqdn => alias_target[:dns_name], :lb_zone => 'Z2222222222')
128
+ end
129
+ end
130
+
131
+ describe "remove_alias_records" do
132
+ it "delegates to Route53Interface" do
133
+ zones = [{:aws_id=>"/hostedzone/Z111111111111", :name=>"example.net."}]
134
+ @mock_interface.stub!(:list_hosted_zones).and_return(zones)
135
+
136
+ alias_target = { :hosted_zone_id => 'Z2222222222', :dns_name => 'example-1111111111.us-east-1.elb.amazonaws.com.' }
137
+ alias_record = { :name => 'example.net.', :type => 'A', :alias_target => alias_target }
138
+ @mock_interface.should_receive(:list_resource_record_sets).with(/Z111111111111/).and_return([alias_record])
139
+ @mock_interface.should_receive(:delete_resource_record_sets).with(/Z111111111111/, [alias_record.dup])
140
+
141
+ @r53.remove_alias_records('example.net')
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ class SampleServer < Awsborn::Server
4
+ instance_type :m1_small
5
+ image_id 'ami-2fc2e95b'
6
+ keys :all
7
+ end
8
+
9
+ describe Awsborn::ServerCluster do
10
+
11
+ before(:each) do
12
+ Awsborn.verbose = false
13
+ end
14
+
15
+ describe "build" do
16
+ it "adds the domain to servers" do
17
+ c = Awsborn::ServerCluster.build SampleServer, 'foo' do
18
+ domain 'example.org'
19
+ server :name, :ip => 'www'
20
+ end
21
+ c.first.elastic_ip.should == 'www.example.org'
22
+ end
23
+ it "adds the domain to load balancers" do
24
+ c = Awsborn::ServerCluster.build SampleServer, 'foo' do
25
+ domain 'example.org'
26
+ load_balancer 'elbe', :dns_alias => 'www', :region => 'eu-west-1'
27
+ end
28
+ c.load_balancers.first.dns_alias.should == 'www.example.org'
29
+ end
30
+ end
31
+
32
+
33
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awsborn
3
3
  version: !ruby/object:Gem::Version
4
- hash: 61
4
+ hash: 59
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 8
9
- - 1
10
- version: 0.8.1
9
+ - 2
10
+ version: 0.8.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - David Vrensk
@@ -16,23 +16,23 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-08-16 00:00:00 +02:00
19
+ date: 2011-08-23 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
- name: right_aws
23
+ name: icehouse-right_aws
24
24
  prerelease: false
25
25
  requirement: &id001 !ruby/object:Gem::Requirement
26
26
  none: false
27
27
  requirements:
28
28
  - - ">="
29
29
  - !ruby/object:Gem::Version
30
- hash: 11
30
+ hash: 7
31
31
  segments:
32
32
  - 2
33
- - 1
33
+ - 2
34
34
  - 0
35
- version: 2.1.0
35
+ version: 2.2.0
36
36
  type: :runtime
37
37
  version_requirements: *id001
38
38
  - !ruby/object:Gem::Dependency
@@ -127,12 +127,15 @@ files:
127
127
  - lib/awsborn/known_hosts_updater.rb
128
128
  - lib/awsborn/load_balancer.rb
129
129
  - lib/awsborn/rake.rb
130
+ - lib/awsborn/route53.rb
130
131
  - lib/awsborn/server.rb
131
132
  - lib/awsborn/server_cluster.rb
132
133
  - spec/aws_constants_spec.rb
133
134
  - spec/ec2_spec.rb
134
135
  - spec/elb_spec.rb
135
136
  - spec/load_balancer_spec.rb
137
+ - spec/route53_spec.rb
138
+ - spec/server_cluster_spec.rb
136
139
  - spec/server_spec.rb
137
140
  - spec/spec.opts
138
141
  - spec/spec_helper.rb