awsborn 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|