1
0
Fork 0
mirror of https://github.com/fog/fog-aws.git synced 2022-11-09 13:50:52 -05:00

Merge pull request #57 from lanej/fix-dns-get

[dns] fix Records#get, mock records and proper errors
This commit is contained in:
Wesley Beary 2015-02-24 08:59:26 -06:00
commit cba35fb5be
10 changed files with 102 additions and 124 deletions

View file

@ -79,7 +79,7 @@ module Fog
# :aws_secret_access_key in order to create a connection
#
# ==== Examples
# dns = Fog::AWS::DNS.new(
# dns = Fog::DNS::AWS.new(
# :aws_access_key_id => your_aws_access_key_id,
# :aws_secret_access_key => your_aws_secret_access_key
# )
@ -141,6 +141,19 @@ module Fog
def _request(params, &block)
@connection.request(params, &block)
rescue Excon::Errors::HTTPStatusError => error
match = Fog::AWS::Errors.match_error(error)
if match.empty?
raise
else
case match[:code]
when 'NoSuchHostedZone', 'NoSuchChange' then
Fog::DNS::AWS::NotFound.slurp(error, match[:message])
else
Fog::DNS::AWS::Error.slurp(error, "#{match[:code]} => #{match[:message]}")
end
end
end
def signature(params)

View file

@ -81,32 +81,26 @@ module Fog
record_type = record_type.upcase unless record_type.nil?
options = {
:max_items => 1,
:name => record_name,
:type => record_type,
:max_items => 1,
:name => record_name,
:type => record_type,
:identifier => record_identifier
}
options.delete_if {|key, value| value.nil?}
data = service.list_resource_record_sets(zone.id, options).body
# Get first record
data = data['ResourceRecordSets'].shift
if data
record = new(data)
# make sure everything matches
if record.name == record_name
if (!record_type.nil? && record.type != record_type) ||
(!record_identifier.nil? && record.set_identifier != record_identifier)
nil
else
record
end
# look for an exact match in the records
(data['ResourceRecordSets'] || []).map do |record_data|
record = new(record_data)
if (record.name == record_name) &&
(record_type.nil? || (record.type == record_type)) &&
(record_identifier.nil? || (record.set_identifier == record_identifier))
record
end
else
nil
end
rescue Excon::Errors::NotFound
end.compact.first
rescue Fog::DNS::AWS::NotFound
nil
end

View file

@ -20,7 +20,7 @@ module Fog
def get(zone_id)
data = service.get_hosted_zone(zone_id).body
new(data)
rescue Excon::Errors::NotFound
rescue Fog::DNS::AWS::NotFound
nil
end
end

View file

@ -155,20 +155,25 @@ module Fog
response = Excon::Response.new
errors = []
if (zone = self.data[:zones][zone_id])
response.status = 200
change_id = Fog::AWS::Mock.change_id
change_batch.each do |change|
change_name = change[:name]
change_name = change_name + "." unless change_name.end_with?(".")
case change[:action]
when "CREATE"
if zone[:records][change[:type]].nil?
zone[:records][change[:type]] = {}
end
if zone[:records][change[:type]][change[:name]].nil?
if zone[:records][change[:type]][change_name].nil?
# raise change.to_s if change[:resource_records].nil?
zone[:records][change[:type]][change[:name]] =
zone[:records][change[:type]][change_name] =
if change[:alias_target]
record = {
:alias_target => change[:alias_target]
@ -178,17 +183,17 @@ module Fog
:ttl => change[:ttl].to_s,
}
end
zone[:records][change[:type]][change[:name]] = {
:change_id => change_id,
zone[:records][change[:type]][change_name] = {
:change_id => change_id,
:resource_records => change[:resource_records] || [],
:name => change[:name],
:type => change[:type]
:name => change_name,
:type => change[:type]
}.merge(record)
else
errors << "Tried to create resource record set #{change[:name]}. type #{change[:type]}, but it already exists"
end
when "DELETE"
if zone[:records][change[:type]].nil? || zone[:records][change[:type]].delete(change[:name]).nil?
if zone[:records][change[:type]].nil? || zone[:records][change[:type]].delete(change_name).nil?
errors << "Tried to delete resource record set #{change[:name]}. type #{change[:type]}, but it was not found"
end
end
@ -196,35 +201,30 @@ module Fog
if errors.empty?
change = {
:id => change_id,
:status => 'PENDING',
:id => change_id,
:status => 'PENDING',
:submitted_at => Time.now.utc.iso8601
}
self.data[:changes][change[:id]] = change
response.body = {
'Id' => change[:id],
'Status' => change[:status],
'Id' => change[:id],
'Status' => change[:status],
'SubmittedAt' => change[:submitted_at]
}
response
else
response.status = 400
response.body = "<?xml version=\"1.0\"?><InvalidChangeBatch xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Messages>#{errors.map {|e| "<Message>#{e}</Message>"}.join()}</Messages></InvalidChangeBatch>"
raise(Excon::Errors.status_error({:expects => 200}, response))
raise Fog::DNS::AWS::Error.new("InvalidChangeBatch => #{errors.join(", ")}")
end
else
response.status = 404
response.body = "<?xml version=\"1.0\"?><Response><Errors><Error><Code>NoSuchHostedZone</Code><Message>A hosted zone with the specified hosted zone ID does not exist.</Message></Error></Errors><RequestID>#{Fog::AWS::Mock.request_id}</RequestID></Response>"
raise(Excon::Errors.status_error({:expects => 200}, response))
raise Fog::DNS::AWS::NotFound.new("NoSuchHostedZone => A hosted zone with the specified hosted zone ID does not exist.")
end
end
end
def self.hosted_zone_for_alias_target(dns_name)
k = elb_hosted_zone_mapping.keys.find do |k|
elb_hosted_zone_mapping.select { |k, _|
dns_name =~ /\A.+\.#{k}\.elb\.amazonaws\.com\.?\z/
end
elb_hosted_zone_mapping[k]
}.last
end
def self.elb_hosted_zone_mapping

View file

@ -97,9 +97,7 @@ module Fog
}
response
else
response.status = 400
response.body = "<?xml version=\"1.0\"?><Response><Errors><Error><Code>DelegationSetNotAvailable</Code><Message>Amazon Route 53 allows some duplication, but Amazon Route 53 has a maximum threshold of duplicated domains. This error is generated when you reach that threshold. In this case, the error indicates that too many hosted zones with the given domain name exist. If you want to create a hosted zone and Amazon Route 53 generates this error, contact Customer Support.</Message></Error></Errors><RequestID>#{Fog::AWS::Mock.request_id}</RequestID></Response>"
raise(Excon::Errors.status_error({:expects => 200}, response))
raise Fog::DNS::AWS::Error.new("DelegationSetNotAvailable => Amazon Route 53 allows some duplication, but Amazon Route 53 has a maximum threshold of duplicated domains. This error is generated when you reach that threshold. In this case, the error indicates that too many hosted zones with the given domain name exist. If you want to create a hosted zone and Amazon Route 53 generates this error, contact Customer Support.")
end
end
end

View file

@ -36,14 +36,17 @@ module Fog
def delete_hosted_zone(zone_id)
response = Excon::Response.new
key = [zone_id, "/hostedzone/#{zone_id}"].find{|k| !self.data[:zones][k].nil?}
if key
key = [zone_id, "/hostedzone/#{zone_id}"].find { |k| !self.data[:zones][k].nil? } ||
raise(Fog::DNS::AWS::NotFound.new("NoSuchHostedZone => A hosted zone with the specified hosted zone does not exist."))
change = {
:id => Fog::AWS::Mock.change_id,
:status => 'INSYNC',
:submitted_at => Time.now.utc.iso8601
}
self.data[:changes][change[:id]] = change
response.status = 200
response.body = {
'ChangeInfo' => {
@ -54,11 +57,6 @@ module Fog
}
self.data[:zones].delete(key)
response
else
response.status = 404
response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>The specified hosted zone does not exist.</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
raise(Excon::Errors.status_error({:expects => 200}, response))
end
end
end
end

View file

@ -35,23 +35,18 @@ module Fog
response = Excon::Response.new
# find the record with matching change_id
# records = data[:zones].values.map{|z| z[:records].values.map{|r| r.values}}.flatten
change = self.data[:changes][change_id]
change = self.data[:changes][change_id] ||
raise(Fog::DNS::AWS::NotFound.new("NoSuchChange => Could not find resource with ID: #{change_id}"))
if change
response.status = 200
submitted_at = Time.parse(change[:submitted_at])
response.body = {
'Id' => change[:id],
# set as insync after some time
'Status' => (submitted_at + Fog::Mock.delay) < Time.now ? 'INSYNC' : change[:status],
'SubmittedAt' => change[:submitted_at]
}
response
else
response.status = 404
response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchChange</Code><Message>Could not find resource with ID: #{change_id}</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
raise(Excon::Errors.status_error({:expects => 200}, response))
end
response.status = 200
submitted_at = Time.parse(change[:submitted_at])
response.body = {
'Id' => change[:id],
# set as insync after some time
'Status' => (submitted_at + Fog::Mock.delay) < Time.now ? 'INSYNC' : change[:status],
'SubmittedAt' => change[:submitted_at]
}
response
end
end
end

View file

@ -51,9 +51,7 @@ module Fog
}
response
else
response.status = 404
response.body = "<?xml version=\"1.0\"?><ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>The specified hosted zone does not exist.</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
raise(Excon::Errors.status_error({:expects => 200}, response))
raise Fog::DNS::AWS::NotFound.new("NoSuchHostedZone => A hosted zone with the specified hosted zone ID does not exist.")
end
end
end

View file

@ -64,19 +64,15 @@ module Fog
response = Excon::Response.new
zone = self.data[:zones][zone_id]
if zone.nil?
response.status = 404
response.body = "<?xml version=\"1.0\"?>\n<ErrorResponse xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Error><Type>Sender</Type><Code>NoSuchHostedZone</Code><Message>No hosted zone found with ID: #{zone_id}</Message></Error><RequestId>#{Fog::AWS::Mock.request_id}</RequestId></ErrorResponse>"
raise(Excon::Errors.status_error({:expects => 200}, response))
end
zone = self.data[:zones][zone_id] ||
raise(Fog::DNS::AWS::NotFound.new("NoSuchHostedZone => A hosted zone with the specified hosted zone ID does not exist."))
records = if options[:type]
records_type = zone[:records][options[:type]]
records_type.values if records_type
else
zone[:records].values.map{|r| r.values}.flatten
end
records_type = zone[:records][options[:type]]
records_type.values if records_type
else
zone[:records].values.map{|r| r.values}.flatten
end
records ||= []
@ -86,7 +82,6 @@ module Fog
if options[:name]
name = options[:name].gsub(zone[:name],"")
records = records.select{|r| r[:name].gsub(zone[:name],"") >= name }
require 'pp'
end
next_record = records[maxitems]

View file

@ -119,13 +119,12 @@ Shindo.tests('Fog::DNS[:aws] | DNS requests', ['aws', 'dns']) do
change_batch << resource_record_set
options = { :comment => 'add A record to domain'}
response = @r53_connection.change_resource_record_sets(@zone_id, change_batch, options)
if response.status == 200
change_id = response.body['Id']
status = response.body['Status']
@new_records << resource_record
end
response.status == 200
Fog.wait_for { @r53_connection.get_change(response.body["Id"]).body["Status"] != "PENDING" }
@new_records << resource_record
@r53_connection.get_change(response.body["Id"]).body["Status"] == "INSYNC"
}
test("add a CNAME resource record") {
@ -139,13 +138,12 @@ Shindo.tests('Fog::DNS[:aws] | DNS requests', ['aws', 'dns']) do
change_batch << resource_record_set
options = { :comment => 'add CNAME record to domain'}
response = @r53_connection.change_resource_record_sets( @zone_id, change_batch, options)
if response.status == 200
change_id = response.body['Id']
status = response.body['Status']
@new_records << resource_record
end
response.status == 200
Fog.wait_for { @r53_connection.get_change(response.body["Id"]).body["Status"] != "PENDING" }
@new_records << resource_record
@r53_connection.get_change(response.body["Id"]).body["Status"] == "INSYNC"
}
test("add a MX resource record") {
@ -159,13 +157,12 @@ Shindo.tests('Fog::DNS[:aws] | DNS requests', ['aws', 'dns']) do
change_batch << resource_record_set
options = { :comment => 'add MX record to domain'}
response = @r53_connection.change_resource_record_sets( @zone_id, change_batch, options)
if response.status == 200
change_id = response.body['Id']
status = response.body['Status']
@new_records << resource_record
end
response.status == 200
Fog.wait_for { @r53_connection.get_change(response.body["Id"]).body["Status"] != "PENDING" }
@new_records << resource_record
@r53_connection.get_change(response.body["Id"]).body["Status"] == "INSYNC"
}
test("add an ALIAS resource record") {
@ -195,47 +192,37 @@ Shindo.tests('Fog::DNS[:aws] | DNS requests', ['aws', 'dns']) do
puts "DNS Name (ELB): #{dns_name}"
puts "Zone ID for Route 53: #{@zone_id}"
sleep 120 unless Fog.mocking?
response = @r53_connection.change_resource_record_sets(@zone_id, change_batch, options)
if response.status == 200
change_id = response.body['Id']
status = response.body['Status']
@new_records << resource_record
end
response.status == 200
Fog.wait_for { @r53_connection.get_change(response.body["Id"]).body["Status"] != "PENDING" }
@new_records << resource_record
@r53_connection.get_change(response.body["Id"]).body["Status"] == "INSYNC"
}
tests("list resource records").formats(AWS::DNS::Formats::LIST_RESOURCE_RECORD_SETS) {
# get resource records for zone
@r53_connection.list_resource_record_sets(@zone_id).body
}
test("delete #{@new_records.count} resource records") {
result = true
change_batch = @new_records.map { |record| record.merge(:action => 'DELETE') }
options = { :comment => 'remove records from domain'}
change_batch = []
@new_records.each { |record|
resource_record_set = record.merge( :action => 'DELETE')
change_batch << resource_record_set
}
options = { :comment => 'remove records from domain'}
response = @r53_connection.change_resource_record_sets(@zone_id, change_batch, options)
if response.status != 200
result = false
break
end
result
Fog.wait_for { @r53_connection.get_change(response.body["Id"]).body["Status"] != "PENDING" }
@r53_connection.get_change(response.body["Id"]).body["Status"] == "INSYNC"
}
test("delete hosted zone #{@zone_id}") {
# cleanup the ELB as well
@elb_connection.delete_load_balancer("fog")
response = @r53_connection.delete_hosted_zone(@zone_id)
response.status == 200
@r53_connection.delete_hosted_zone(@zone_id).status == 200
}
end
@ -243,13 +230,13 @@ Shindo.tests('Fog::DNS[:aws] | DNS requests', ['aws', 'dns']) do
tests('failure') do
tests('create hosted zone using invalid domain name').raises(Excon::Errors::BadRequest) do
pending if Fog.mocking?
response = @r53_connection.create_hosted_zone('invalid-domain')
@r53_connection.create_hosted_zone('invalid-domain')
end
tests('get hosted zone using invalid ID').raises(Excon::Errors::NotFound) do
pending if Fog.mocking?
zone_id = 'dummy-id'
response = @r53_connection.get_hosted_zone(zone_id)
@r53_connection.get_hosted_zone(zone_id)
end
end