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 +3 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/awsborn.gemspec +8 -5
- data/lib/awsborn/elb.rb +4 -0
- data/lib/awsborn/load_balancer.rb +51 -16
- data/lib/awsborn/rake.rb +14 -2
- data/lib/awsborn/route53.rb +70 -0
- data/lib/awsborn/server_cluster.rb +19 -5
- data/spec/elb_spec.rb +7 -0
- data/spec/load_balancer_spec.rb +83 -15
- data/spec/route53_spec.rb +145 -0
- data/spec/server_cluster_spec.rb +33 -0
- metadata +11 -8
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.
|
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
|
+
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.
|
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-
|
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.
|
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.
|
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.
|
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
|
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
|
101
|
+
def launch_or_update (running_servers)
|
98
102
|
launch unless running?
|
99
103
|
|
100
|
-
|
101
|
-
|
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
|
-
|
107
|
-
|
107
|
+
configure_dns if @dns_alias
|
108
|
+
end
|
108
109
|
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
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)
|
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.
|
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
|
-
|
100
|
-
|
101
|
-
|
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'], [])
|
data/spec/load_balancer_spec.rb
CHANGED
@@ -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
|
-
|
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
|
-
:
|
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 "
|
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
|
-
).
|
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 "
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
-
|
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:
|
4
|
+
hash: 59
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 8
|
9
|
-
-
|
10
|
-
version: 0.8.
|
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-
|
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:
|
30
|
+
hash: 7
|
31
31
|
segments:
|
32
32
|
- 2
|
33
|
-
-
|
33
|
+
- 2
|
34
34
|
- 0
|
35
|
-
version: 2.
|
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
|