Permalink
Browse files

Support same name public/private hz

  • Loading branch information...
Genki Sugawara
Genki Sugawara committed Jun 30, 2015
1 parent 80741b1 commit 614df65ee8f2f3f922586bc22ccd20dfe5b78e46
Showing with 78 additions and 217 deletions.
  1. +1 −0 .gitignore
  2. +2 −0 README.md
  3. +16 −6 lib/roadworker/client.rb
  4. +1 −6 lib/roadworker/dsl.rb
  5. +0 −177 spec/roadworker_mix_spec.rb
  6. +58 −28 spec/roadworker_update_private_spec.rb
@@ -17,3 +17,4 @@ test/version_tmp
tmp
test.rb
Routefile
/_site
@@ -12,6 +12,8 @@ It defines the state of Route53 using DSL, and updates Route53 according to DSL.

* Roadworker cannot update TTL of two or more same weighted A records (with different SetIdentifier) after creation.
* `>= 0.4.3` compare resource records ignoring the order.
* `>= 0.5.5`
* **Disable Divided HostedZone**

## Installation

@@ -65,13 +65,15 @@ def load_file(file)
end

def walk_hosted_zones(dsl)
expected = collection_to_hash(dsl.hosted_zones, :name)
actual = collection_to_hash(@route53.hosted_zones, :name)
expected = collection_to_hash(dsl.hosted_zones) {|i| [normalize_name(i.name), i.vpcs.empty?] }
actual = collection_to_hash(@route53.hosted_zones) {|i| [normalize_name(i.name), i.vpcs.empty?] }

expected.each do |keys, expected_zone|
name = keys[0]
next unless matched_zone?(name)
actual_zone = actual.delete(keys) || @route53.hosted_zones.create(name, :vpc => expected_zone.vpcs.first)
actual_zone = actual.delete(keys)
actual_zone ||= @route53.hosted_zones.create(name, :vpc => expected_zone.vpcs.first)

walk_vpcs(expected_zone, actual_zone)
walk_rrsets(expected_zone, actual_zone)
end
@@ -140,9 +142,13 @@ def collection_to_hash(collection, *keys)
hash = {}

collection.each do |item|
key_list = keys.map do |k|
value = item.send(k)
(k == :name && value) ? value.downcase.sub(/\.\Z/, '') : value
if block_given?
key_list = yield(item)
else
key_list = keys.map do |k|
value = item.send(k)
(k == :name && value) ? normalize_name(value) : value
end
end

hash[key_list] = item
@@ -151,5 +157,9 @@ def collection_to_hash(collection, *keys)
return hash
end

def normalize_name(name)
name.downcase.sub(/\.\Z/, '')
end

end # Client
end # Roadworker
@@ -40,12 +40,7 @@ def require(file)
end

def hosted_zone(name, &block)
if (hz = @result.hosted_zones.find {|i| i.name == name })
@result.hosted_zones.reject! {|i| i.name == name }
@result.hosted_zones << HostedZone.new(name, hz.rrsets, &block).result
else
@result.hosted_zones << HostedZone.new(name, [], &block).result
end
@result.hosted_zones << HostedZone.new(name, [], &block).result
end

class HostedZone
@@ -662,182 +662,5 @@
expect(rrs_list(aaaa.resource_records.sort_by {|i| i.to_s })).to eq(["::1"])
}
end

context 'Change (Divided)' do
it {
updated = routefile do
<<EOS
hosted_zone "winebarrel.jp" do
rrset "www.winebarrel.jp", "A" do
ttl 123
resource_records(
"127.0.0.1",
)
end

rrset "elb.winebarrel.jp", "A" do
dns_name TEST_ELB
end

rrset "www.winebarrel.jp", "TXT" do
ttl 456
resource_records(
'"v=spf1 +ip4:192.168.100.0/24 ~all"',
'"spf2.0/pra +ip4:192.168.100.0/24 ~all"',
'"spf2.0/mfrom +ip4:192.168.100.0/24 ~all"'
)
end

rrset "ftp.winebarrel.jp", "SRV" do
ttl 123
resource_records(
"1 0 21 server01.example.jp",
"2 0 21 server02.example.jp"
)
end
end

hosted_zone "winebarrel.jp" do
rrset "www.winebarrel.jp", "AAAA" do
ttl 123
resource_records("::1")
end

rrset "fo.winebarrel.jp", "A" do
set_identifier "Primary"
failover "PRIMARY"
health_check "http://192.0.43.10:80/path", 'example.com'
ttl 456
resource_records(
"127.0.0.1",
"127.0.0.2"
)
end

rrset "fo.winebarrel.jp", "A" do
set_identifier "Secondary"
failover "SECONDARY"
health_check "tcp://192.0.43.10:3306"
ttl 456
resource_records(
"127.0.0.3",
"127.0.0.4"
)
end
end

hosted_zone "333.222.111.in-addr.arpa" do
rrset "444.333.222.111.in-addr.arpa", "PTR" do
ttl 123
resource_records("www.winebarrel.jp")
end
end
EOS
end

expect(updated).to be_truthy

zones = @route53.hosted_zones.to_a.sort_by {|i| i.name }
expect(zones.length).to eq(3)

ptr_zone = zones[0]
expect(ptr_zone.name).to eq("333.222.111.in-addr.arpa.")
expect(ptr_zone.resource_record_set_count).to eq(3)

expect(ptr_zone.rrsets['333.222.111.in-addr.arpa.', 'NS'].ttl).to eq(172800)
expect(ptr_zone.rrsets['333.222.111.in-addr.arpa.', 'SOA'].ttl).to eq(900)

ptr = ptr_zone.rrsets['444.333.222.111.in-addr.arpa.', 'PTR']
expect(ptr.name).to eq("444.333.222.111.in-addr.arpa.")
expect(ptr.ttl).to eq(123)
expect(rrs_list(ptr.resource_records.sort_by {|i| i.to_s })).to eq(["www.winebarrel.jp"])

info_zone = zones[1]
expect(info_zone.name).to eq("info.winebarrel.jp.")
expect(info_zone.resource_record_set_count).to eq(3)

expect(info_zone.rrsets['info.winebarrel.jp.', 'NS'].ttl).to eq(172800)
expect(info_zone.rrsets['info.winebarrel.jp.', 'SOA'].ttl).to eq(900)

info_a = info_zone.rrsets['info.winebarrel.jp.', 'A']
expect(info_a.name).to eq("info.winebarrel.jp.")
expect(info_a.ttl).to eq(123)
expect(rrs_list(info_a.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.3", "127.0.0.4"])

zone = zones[2]
expect(zone.name).to eq("winebarrel.jp.")
expect(zone.resource_record_set_count).to eq(9)

expect(zone.rrsets['winebarrel.jp.', 'NS'].ttl).to eq(172800)
expect(zone.rrsets['winebarrel.jp.', 'SOA'].ttl).to eq(900)

a = zone.rrsets['www.winebarrel.jp.', 'A']
expect(a.name).to eq("www.winebarrel.jp.")
expect(a.ttl).to eq(123)
expect(rrs_list(a.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.1"])

a_alias = zone.rrsets['elb.winebarrel.jp.', 'A']
expect(a_alias.name).to eq("elb.winebarrel.jp.")
expect(a_alias.alias_target).to eq({
:hosted_zone_id => "Z2YN17T5R711GT",
:dns_name => TEST_ELB,
:evaluate_target_health => false,
})

txt = zone.rrsets['www.winebarrel.jp.', 'TXT']
expect(txt.name).to eq("www.winebarrel.jp.")
expect(txt.ttl).to eq(456)
expect(rrs_list(txt.resource_records.sort_by {|i| i.to_s })).to eq([
"\"spf2.0/mfrom +ip4:192.168.100.0/24 ~all\"",
"\"spf2.0/pra +ip4:192.168.100.0/24 ~all\"",
"\"v=spf1 +ip4:192.168.100.0/24 ~all\"",
])

srv = zone.rrsets['ftp.winebarrel.jp.', 'SRV']
expect(srv.name).to eq("ftp.winebarrel.jp.")
expect(srv.ttl).to eq(123)
expect(rrs_list(srv.resource_records.sort_by {|i| i.to_s })).to eq([
"1 0 21 server01.example.jp",
"2 0 21 server02.example.jp",
])

aaaa = zone.rrsets['www.winebarrel.jp.', 'AAAA']
expect(aaaa.name).to eq("www.winebarrel.jp.")
expect(aaaa.ttl).to eq(123)
expect(rrs_list(aaaa.resource_records.sort_by {|i| i.to_s })).to eq(["::1"])
check_list = fetch_health_checks(@route53)
expect(check_list.length).to eq(2)

fo_p = zone.rrsets['fo.winebarrel.jp.', 'A', "Primary"]
expect(fo_p.name).to eq("fo.winebarrel.jp.")
expect(fo_p.set_identifier).to eq('Primary')
expect(fo_p.failover).to eq('PRIMARY')
expect(fo_p.ttl).to eq(456)
expect(rrs_list(fo_p.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.1", "127.0.0.2"])
expect(check_list[fo_p.health_check_id]).to eq({
:ip_address => '192.0.43.10',
:port => 80,
:type => 'HTTP',
:resource_path => '/path',
:fully_qualified_domain_name => 'example.com',
:request_interval => 30,
:failure_threshold => 3,
})

fo_s = zone.rrsets['fo.winebarrel.jp.', 'A', "Secondary"]
expect(fo_s.name).to eq("fo.winebarrel.jp.")
expect(fo_s.set_identifier).to eq('Secondary')
expect(fo_s.failover).to eq('SECONDARY')
expect(fo_s.ttl).to eq(456)
expect(rrs_list(fo_s.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.3", "127.0.0.4"])
expect(check_list[fo_s.health_check_id]).to eq({
:ip_address => '192.0.43.10',
:port => 3306,
:type => 'TCP',
:request_interval => 30,
:failure_threshold => 3,
})
}
end
end
end
@@ -117,7 +117,7 @@
}
end

context 'associate to public' do
context 'both public/private' do
before {
routefile do
<<EOS
@@ -151,27 +151,42 @@
EOS
end

zones = @route53.hosted_zones.to_a
expect(zones.length).to eq(1)
zones = @route53.hosted_zones.to_a.sort_by {|i| i.vpcs.length }
expect(zones.length).to eq(2)

zone = zones[0]
expect(zone.name).to eq("winebarrel.jp.")
expect(zone.resource_record_set_count).to eq(3)
# Public
zone1 = zones[0]
expect(zone1.name).to eq("winebarrel.jp.")
expect(zone1.resource_record_set_count).to eq(3)

expect(zone.rrsets['winebarrel.jp.', 'NS'].ttl).to eq(172800)
expect(zone.rrsets['winebarrel.jp.', 'SOA'].ttl).to eq(900)
expect(zone1.rrsets['winebarrel.jp.', 'NS'].ttl).to eq(172800)
expect(zone1.rrsets['winebarrel.jp.', 'SOA'].ttl).to eq(900)

# Cannot associate VPC to public zone
expect(zone.vpcs).to match_array []
expect(zone1.vpcs).to match_array []

a = zone.rrsets['www.winebarrel.jp.', 'A']
expect(a.name).to eq("www.winebarrel.jp.")
expect(a.ttl).to eq(456)
expect(rrs_list(a.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.3", "127.0.0.4"])
a1 = zone1.rrsets['www.winebarrel.jp.', 'A']
expect(a1.name).to eq("www.winebarrel.jp.")
expect(a1.ttl).to eq(123)
expect(rrs_list(a1.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.1", "127.0.0.2"])

# Private
zone2 = zones[1]
expect(zone2.name).to eq("winebarrel.jp.")
expect(zone2.resource_record_set_count).to eq(3)

expect(zone2.rrsets['winebarrel.jp.', 'NS'].ttl).to eq(172800)
expect(zone2.rrsets['winebarrel.jp.', 'SOA'].ttl).to eq(900)

expect(zone2.vpcs).to match_array [{vpc_region: TEST_VPC_REGION, vpc_id: TEST_VPC1}]

a2 = zone2.rrsets['www.winebarrel.jp.', 'A']
expect(a2.name).to eq("www.winebarrel.jp.")
expect(a2.ttl).to eq(456)
expect(rrs_list(a2.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.3", "127.0.0.4"])
}
end

context 'disassociate all vpc' do
context 'both private/public' do
before {
routefile do
<<EOS
@@ -205,25 +220,40 @@
EOS
end

zones = @route53.hosted_zones.to_a
expect(zones.length).to eq(1)
zones = @route53.hosted_zones.to_a.sort_by {|i| i.vpcs.length }
expect(zones.length).to eq(2)

zone = zones[0]
expect(zone.name).to eq("winebarrel.jp.")
expect(zone.resource_record_set_count).to eq(3)
# Public
zone1 = zones[0]
expect(zone1.name).to eq("winebarrel.jp.")
expect(zone1.resource_record_set_count).to eq(3)

expect(zone.rrsets['winebarrel.jp.', 'NS'].ttl).to eq(172800)
expect(zone.rrsets['winebarrel.jp.', 'SOA'].ttl).to eq(900)
expect(zone1.rrsets['winebarrel.jp.', 'NS'].ttl).to eq(172800)
expect(zone1.rrsets['winebarrel.jp.', 'SOA'].ttl).to eq(900)

# Private zone requires one or more of VPCs
expect(zone.vpcs).to match_array [
expect(zone1.vpcs).to match_array []

a1 = zone1.rrsets['www.winebarrel.jp.', 'A']
expect(a1.name).to eq("www.winebarrel.jp.")
expect(a1.ttl).to eq(456)
expect(rrs_list(a1.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.3", "127.0.0.4"])

# Private
zone2 = zones[1]
expect(zone2.name).to eq("winebarrel.jp.")
expect(zone2.resource_record_set_count).to eq(3)

expect(zone2.rrsets['winebarrel.jp.', 'NS'].ttl).to eq(172800)
expect(zone2.rrsets['winebarrel.jp.', 'SOA'].ttl).to eq(900)

expect(zone2.vpcs).to match_array [
{:vpc_region => TEST_VPC_REGION, :vpc_id => TEST_VPC1},
]

a = zone.rrsets['www.winebarrel.jp.', 'A']
expect(a.name).to eq("www.winebarrel.jp.")
expect(a.ttl).to eq(456)
expect(rrs_list(a.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.3", "127.0.0.4"])
a2 = zone2.rrsets['www.winebarrel.jp.', 'A']
expect(a2.name).to eq("www.winebarrel.jp.")
expect(a2.ttl).to eq(123)
expect(rrs_list(a2.resource_records.sort_by {|i| i.to_s })).to eq(["127.0.0.1", "127.0.0.2"])
}
end
end

0 comments on commit 614df65

Please sign in to comment.