route53 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/Rakefile +5 -0
- data/lib/route53.rb +5 -411
- data/lib/route53/aws_response.rb +83 -0
- data/lib/route53/connection.rb +93 -0
- data/lib/route53/dns_record.rb +99 -0
- data/lib/route53/version.rb +1 -1
- data/lib/route53/zone.rb +134 -0
- data/route53.gemspec +9 -2
- data/spec/fixtures/vcr_cassettes/aws_zone.yml +198 -0
- data/spec/fixtures/vcr_cassettes/aws_zone_delete.yml +110 -0
- data/spec/fixtures/vcr_cassettes/aws_zone_records.yml +73 -0
- data/spec/fixtures/vcr_cassettes/aws_zones.yml +71 -0
- data/spec/lib/route53/aws_response_spec.rb +10 -0
- data/spec/lib/route53/connection_spec.rb +62 -0
- data/spec/lib/route53/dns_record_spec.rb +4 -0
- data/spec/lib/route53/zone_spec.rb +71 -0
- data/spec/spec_helper.rb +20 -0
- metadata +162 -80
@@ -0,0 +1,83 @@
|
|
1
|
+
module Route53
|
2
|
+
class AWSResponse
|
3
|
+
attr_reader :raw_data
|
4
|
+
|
5
|
+
MESSAGES = {
|
6
|
+
"InvalidClientTokenId" => "You may have a missing or incorrect secret or access key. Please double check your configuration files and amazon account",
|
7
|
+
"MissingAuthenticationToken" => "You may have a missing or incorrect secret or access key. Please double check your configuration files and amazon account",
|
8
|
+
"OptInRequired" => "In order to use Amazon's Route 53 service you first need to signup for it. Please see http://aws.amazon.com/route53/ for your account information and use the associated access key and secret.",
|
9
|
+
"Other" => "It looks like you've run into an unhandled error. Please send a detailed bug report with the entire input and output from the program to support@50projects.com or to https://github.com/pcorliss/ruby_route_53/issues and we'll do out best to help you.",
|
10
|
+
"SignatureDoesNotMatch" => "It looks like your secret key is incorrect or no longer valid. Please check your amazon account information for the proper key.",
|
11
|
+
"HostedZoneNotEmpty" => "You'll need to first delete the contents of this zone. You can do so using the '--remove' option as part of the command line interface.",
|
12
|
+
"InvalidChangeBatch" => "You may have tried to delete a NS or SOA record. This error is safe to ignore if you're just trying to delete all records as part of a zone prior to deleting the zone. Or you may have tried to create a record that already exists. Otherwise please file a bug by sending a detailed bug report with the entire input and output from the program to support@50projects.com or to https://github.com/pcorliss/ruby_route_53/issues and we'll do out best to help you.",
|
13
|
+
"ValidationError" => "Check over your input again to make sure the record to be created is valid. The error message should give you some hints on what went wrong. If you're still having problems please file a bug by sending a detailed bug report with the entire input and output from the program to support@50projects.com or to https://github.com/pcorliss/ruby_route_53/issues and we'll do out best to help you.",
|
14
|
+
"ServiceUnavailable" => "It looks like Amazon Route 53 is having availability problems. If the error persists, you may want to check http://status.aws.amazon.com/ for more information on the current system status."
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(resp,conn)
|
18
|
+
@raw_data = unescape(resp)
|
19
|
+
if error?
|
20
|
+
$stderr.puts "ERROR: Amazon returned an error for the request."
|
21
|
+
$stderr.puts "ERROR: RAW_XML: "+@raw_data
|
22
|
+
$stderr.puts "ERROR: "+error_message
|
23
|
+
$stderr.puts ""
|
24
|
+
$stderr.puts "What now? "+helpful_message
|
25
|
+
#exit 1
|
26
|
+
end
|
27
|
+
@conn = conn
|
28
|
+
@created = Time.now
|
29
|
+
puts "Raw: #{@raw_data}" if @conn.verbose
|
30
|
+
end
|
31
|
+
|
32
|
+
def error?
|
33
|
+
return Nokogiri::XML(@raw_data).search("ErrorResponse").size > 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def error_message
|
37
|
+
xml = Nokogiri::XML(@raw_data)
|
38
|
+
msg_code = xml.search("Code")
|
39
|
+
msg_text = xml.search("Message")
|
40
|
+
return (msg_code.size > 0 ? msg_code.first.inner_text : "") + (msg_text.size > 0 ? ': ' + msg_text.first.inner_text : "")
|
41
|
+
end
|
42
|
+
|
43
|
+
def helpful_message
|
44
|
+
xml = Nokogiri::XML(@raw_data)
|
45
|
+
msg_code = xml.search("Code").first.inner_text
|
46
|
+
MESSAGES[msg_code] || MESSAGES["Other"]
|
47
|
+
end
|
48
|
+
|
49
|
+
def complete?
|
50
|
+
return true if error?
|
51
|
+
if @change_url.nil?
|
52
|
+
change = Nokogiri::XML(@raw_data).search("ChangeInfo")
|
53
|
+
if change.size > 0
|
54
|
+
@change_url = change.first.search("Id").first.inner_text
|
55
|
+
else
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
if @complete.nil? || @complete == false
|
60
|
+
status = Nokogiri::XML(@conn.request(@conn.base_url+@change_url).raw_data).search("Status")
|
61
|
+
@complete = status.size > 0 && status.first.inner_text == "INSYNC" ? true : false
|
62
|
+
if !@complete && @created - Time.now > 60
|
63
|
+
$stderr.puts "WARNING: Amazon Route53 Change timed out on Sync. This may not be an issue as it may just be Amazon being assy. Then again your request may not have completed.'"
|
64
|
+
@complete = true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
return @complete
|
68
|
+
end
|
69
|
+
|
70
|
+
def pending?
|
71
|
+
#Return opposite of complete via XOR
|
72
|
+
return complete? ^ true
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_s
|
76
|
+
return @raw_data
|
77
|
+
end
|
78
|
+
|
79
|
+
def unescape(string)
|
80
|
+
string.gsub(/\\0(\d{2})/) { $1.oct.chr }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Route53
|
2
|
+
class Connection
|
3
|
+
attr_reader :base_url
|
4
|
+
attr_reader :api
|
5
|
+
attr_reader :endpoint
|
6
|
+
attr_reader :verbose
|
7
|
+
|
8
|
+
def initialize(accesskey,secret,api='2012-12-12',endpoint='https://route53.amazonaws.com/',verbose=false,ssl_no_verify=false)
|
9
|
+
@accesskey = accesskey
|
10
|
+
@secret = secret
|
11
|
+
@api = api
|
12
|
+
@endpoint = endpoint
|
13
|
+
@base_url = endpoint+@api
|
14
|
+
@verbose = verbose
|
15
|
+
@ssl_no_verify = ssl_no_verify
|
16
|
+
end
|
17
|
+
|
18
|
+
def request(url,type = "GET",data = nil)
|
19
|
+
puts "URL: #{url}" if @verbose
|
20
|
+
puts "Type: #{type}" if @verbose
|
21
|
+
puts "Req: #{data}" if type != "GET" && @verbose
|
22
|
+
uri = URI(url)
|
23
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
24
|
+
http.use_ssl = true if uri.scheme == "https"
|
25
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if RUBY_VERSION.start_with?("1.8") or @ssl_no_verify
|
26
|
+
time = get_date
|
27
|
+
hmac = HMAC::SHA256.new(@secret)
|
28
|
+
hmac.update(time)
|
29
|
+
signature = Base64.encode64(hmac.digest).chomp
|
30
|
+
headers = {
|
31
|
+
'Date' => time,
|
32
|
+
'X-Amzn-Authorization' => "AWS3-HTTPS AWSAccessKeyId=#{@accesskey},Algorithm=HmacSHA256,Signature=#{signature}",
|
33
|
+
'Content-Type' => 'text/xml; charset=UTF-8'
|
34
|
+
}
|
35
|
+
resp = http.send_request(type,uri.path+"?"+(uri.query.nil? ? "" : uri.query),data,headers)
|
36
|
+
#puts "Resp:"+resp.to_s if @verbose
|
37
|
+
#puts "RespBody: #{resp.body}" if @verbose
|
38
|
+
return AWSResponse.new(resp.body,self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_zones(name = nil)
|
42
|
+
truncated = true
|
43
|
+
query = []
|
44
|
+
zones = []
|
45
|
+
while truncated
|
46
|
+
if !name.nil? && name.start_with?("/hostedzone/")
|
47
|
+
resp = request("#{@base_url}#{name}")
|
48
|
+
truncated = false
|
49
|
+
else
|
50
|
+
resp = request("#{@base_url}/hostedzone?"+query.join("&"))
|
51
|
+
end
|
52
|
+
return nil if resp.error?
|
53
|
+
zone_list = Nokogiri::XML(resp.raw_data)
|
54
|
+
elements = zone_list.search("HostedZone")
|
55
|
+
elements.each do |e|
|
56
|
+
zones.push(Zone.new(e.search("Name").first.inner_text,
|
57
|
+
e.search("Id").first.inner_text,
|
58
|
+
self))
|
59
|
+
end
|
60
|
+
truncated = (zone_list.search("IsTruncated").first.inner_text == "true") if truncated
|
61
|
+
query = ["marker="+zone_list.search("NextMarker").first.inner_text] if truncated
|
62
|
+
end
|
63
|
+
unless name.nil? || name.start_with?("/hostedzone/")
|
64
|
+
name_arr = name.split('.')
|
65
|
+
(0 ... name_arr.size).each do |i|
|
66
|
+
search_domain = name_arr.last(name_arr.size-i).join('.')+"."
|
67
|
+
zone_select = zones.select { |z| z.name == search_domain }
|
68
|
+
return zone_select
|
69
|
+
end
|
70
|
+
return nil
|
71
|
+
end
|
72
|
+
return zones
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_date
|
76
|
+
#return Time.now.utc.rfc2822
|
77
|
+
#Cache date for 30 seconds to reduce extra calls
|
78
|
+
if @date_stale.nil? || @date_stale < Time.now - 30
|
79
|
+
uri = URI(@endpoint)
|
80
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
81
|
+
http.use_ssl = true if uri.scheme == "https"
|
82
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if RUBY_VERSION.start_with?("1.8") or @ssl_no_verify
|
83
|
+
resp = nil
|
84
|
+
puts "Making Date Request" if @verbose
|
85
|
+
http.start { |http| resp = http.head('/date') }
|
86
|
+
@date = resp['Date']
|
87
|
+
@date_stale = Time.now
|
88
|
+
puts "Received Date." if @verbose
|
89
|
+
end
|
90
|
+
return @date
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Route53
|
2
|
+
class DNSRecord
|
3
|
+
attr_reader :name
|
4
|
+
attr_reader :type
|
5
|
+
attr_reader :ttl
|
6
|
+
attr_reader :values
|
7
|
+
attr_reader :weight
|
8
|
+
attr_reader :ident
|
9
|
+
attr_reader :zone_apex
|
10
|
+
|
11
|
+
def initialize(name,type,ttl,values,zone,zone_apex=nil,weight=nil,ident=nil, evaluate_target_health=false)
|
12
|
+
@name = name
|
13
|
+
unless @name.end_with?(".")
|
14
|
+
@name += "."
|
15
|
+
end
|
16
|
+
@type = type.upcase
|
17
|
+
@ttl = ttl
|
18
|
+
@values = values
|
19
|
+
@zone = zone
|
20
|
+
@zone_apex = zone_apex
|
21
|
+
@weight = weight
|
22
|
+
@ident = ident
|
23
|
+
@evaluate_target_health = evaluate_target_health
|
24
|
+
end
|
25
|
+
|
26
|
+
def gen_change_xml(xml,action)
|
27
|
+
xml.Change { |change|
|
28
|
+
change.Action(action.upcase)
|
29
|
+
change.ResourceRecordSet { |record|
|
30
|
+
record.Name(@name)
|
31
|
+
record.Type(@type)
|
32
|
+
record.SetIdentifier(@ident) if @ident
|
33
|
+
record.Weight(@weight) if @weight
|
34
|
+
record.TTL(@ttl) unless @zone_apex
|
35
|
+
if @zone_apex
|
36
|
+
record.AliasTarget { |targets|
|
37
|
+
targets.HostedZoneId(@zone_apex)
|
38
|
+
targets.DNSName(@values.first)
|
39
|
+
targets.EvaluateTargetHealth(@evaluate_target_health)
|
40
|
+
}
|
41
|
+
else
|
42
|
+
record.ResourceRecords { |resources|
|
43
|
+
@values.each { |val|
|
44
|
+
resources.ResourceRecord { |record|
|
45
|
+
record.Value(val)
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
end
|
50
|
+
}
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def delete(comment=nil)
|
55
|
+
@zone.perform_actions([{:action => "DELETE", :record => self}],comment)
|
56
|
+
end
|
57
|
+
|
58
|
+
def create(comment=nil)
|
59
|
+
@zone.perform_actions([{:action => "CREATE", :record => self}],comment)
|
60
|
+
end
|
61
|
+
|
62
|
+
#Need to modify to a param hash
|
63
|
+
def update(name,type,ttl,values,comment=nil, zone_apex = nil)
|
64
|
+
prev = self.clone
|
65
|
+
@name = name unless name.nil?
|
66
|
+
@type = type unless type.nil?
|
67
|
+
@ttl = ttl unless ttl.nil?
|
68
|
+
@values = values unless values.nil?
|
69
|
+
@zone_apex = zone_apex unless zone_apex.nil?
|
70
|
+
@zone.perform_actions([
|
71
|
+
{:action => "DELETE", :record => prev},
|
72
|
+
{:action => "CREATE", :record => self},
|
73
|
+
],comment)
|
74
|
+
end
|
75
|
+
|
76
|
+
#Returns the raw array so the developer can update large batches manually
|
77
|
+
#Need to modify to a param hash
|
78
|
+
def update_dirty(name,type,ttl,values,zone_apex = nil)
|
79
|
+
prev = self.clone
|
80
|
+
@name = name unless name.nil?
|
81
|
+
@type = type unless type.nil?
|
82
|
+
@ttl = ttl unless ttl.nil?
|
83
|
+
@values = values unless values.nil?
|
84
|
+
@zone_apex = zone_apex unless zone_apex.nil?
|
85
|
+
return [{:action => "DELETE", :record => prev},
|
86
|
+
{:action => "CREATE", :record => self}]
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
if @weight
|
91
|
+
"#{@name} #{@type} #{@ttl} '#{@ident}' #{@weight} #{@values.join(",")}"
|
92
|
+
elsif @zone_apex
|
93
|
+
"#{@name} #{@type} #{@zone_apex} #{@values.join(",")}"
|
94
|
+
else
|
95
|
+
"#{@name} #{@type} #{@ttl} #{@values.join(",")}"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/route53/version.rb
CHANGED
data/lib/route53/zone.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
module Route53
|
2
|
+
class Zone
|
3
|
+
attr_reader :host_url
|
4
|
+
attr_reader :name
|
5
|
+
attr_reader :records
|
6
|
+
attr_reader :conn
|
7
|
+
|
8
|
+
def initialize(name,host_url,conn)
|
9
|
+
@name = name
|
10
|
+
unless @name.end_with?(".")
|
11
|
+
@name += "."
|
12
|
+
end
|
13
|
+
@host_url = host_url
|
14
|
+
@conn = conn
|
15
|
+
end
|
16
|
+
|
17
|
+
def nameservers
|
18
|
+
return @nameservers if @nameservers
|
19
|
+
response = Nokogiri::XML(@conn.request(@conn.base_url + @host_url).to_s)
|
20
|
+
@nameservers = response.search("NameServer").map(&:inner_text)
|
21
|
+
@nameservers
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_zone
|
25
|
+
@conn.request(@conn.base_url + @host_url,"DELETE")
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_zone(comment = nil)
|
29
|
+
xml_str = ""
|
30
|
+
xml = Builder::XmlMarkup.new(:target=>xml_str, :indent=>2)
|
31
|
+
xml.instruct!
|
32
|
+
xml.CreateHostedZoneRequest(:xmlns => @conn.endpoint+'doc/'+@conn.api+'/') { |create|
|
33
|
+
create.Name(@name)
|
34
|
+
# AWS lists this as required
|
35
|
+
# "unique string that identifies the request and that
|
36
|
+
# allows failed CreateHostedZone requests to be retried without the risk of executing the operation twice."
|
37
|
+
# Just going to pass a random string instead.
|
38
|
+
create.CallerReference(rand(2**32).to_s(16))
|
39
|
+
create.HostedZoneConfig { |conf|
|
40
|
+
conf.Comment(comment)
|
41
|
+
}
|
42
|
+
}
|
43
|
+
#puts "XML:\n#{xml_str}" if @conn.verbose
|
44
|
+
resp = @conn.request(@conn.base_url + "/hostedzone","POST",xml_str)
|
45
|
+
resp_xml = Nokogiri::XML(resp.raw_data)
|
46
|
+
@host_url = resp_xml.search("HostedZone").first.search("Id").first.inner_text
|
47
|
+
return resp
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_records(type="ANY")
|
51
|
+
return nil if host_url.nil?
|
52
|
+
|
53
|
+
truncated = true
|
54
|
+
query = []
|
55
|
+
dom_records = []
|
56
|
+
while truncated
|
57
|
+
resp = @conn.request(@conn.base_url+@host_url+"/rrset?"+query.join("&"))
|
58
|
+
if resp.error?
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
zone_file = Nokogiri::XML(resp.raw_data)
|
62
|
+
records = zone_file.search("ResourceRecordSet")
|
63
|
+
|
64
|
+
records.each do |record|
|
65
|
+
#puts "Name:"+record.search("Name").first.inner_text if @conn.verbose
|
66
|
+
#puts "Type:"+record.search("Type").first.inner_text if @conn.verbose
|
67
|
+
#puts "TTL:"+record.search("TTL").first.inner_text if @conn.verbose
|
68
|
+
#record.search("Value").each do |val|
|
69
|
+
# #puts "Val:"+val.inner_text if @conn.verbose
|
70
|
+
#end
|
71
|
+
zone_apex_records = record.search("HostedZoneId")
|
72
|
+
values = record.search("Value").map { |val| val.inner_text }
|
73
|
+
values << record.search("DNSName").first.inner_text unless zone_apex_records.empty?
|
74
|
+
weight_records = record.search("Weight")
|
75
|
+
ident_records = record.search("SetIdentifier")
|
76
|
+
dom_records.push(DNSRecord.new(record.search("Name").first.inner_text,
|
77
|
+
record.search("Type").first.inner_text,
|
78
|
+
((record.search("TTL").first.nil? ? '' : record.search("TTL").first.inner_text) if zone_apex_records.empty?),
|
79
|
+
values,
|
80
|
+
self,
|
81
|
+
(zone_apex_records.first.inner_text unless zone_apex_records.empty?),
|
82
|
+
(weight_records.first.inner_text unless weight_records.empty?),
|
83
|
+
(ident_records.first.inner_text unless ident_records.empty?)
|
84
|
+
))
|
85
|
+
end
|
86
|
+
|
87
|
+
truncated = (zone_file.search("IsTruncated").first.inner_text == "true")
|
88
|
+
if truncated
|
89
|
+
next_name = zone_file.search("NextRecordName").first.inner_text
|
90
|
+
next_type = zone_file.search("NextRecordType").first.inner_text
|
91
|
+
query = ["name="+next_name,"type="+next_type]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
@records = dom_records
|
95
|
+
if type != 'ANY'
|
96
|
+
return dom_records.select { |r| r.type == type }
|
97
|
+
end
|
98
|
+
return dom_records
|
99
|
+
end
|
100
|
+
|
101
|
+
#When deleting a record an optional value is available to specify just a single value within a recordset like an MX record
|
102
|
+
#Takes an array of [:action => , :record => ] where action is either CREATE or DELETE and record is a DNSRecord
|
103
|
+
def gen_change_xml(change_list,comment=nil)
|
104
|
+
#Get zone list and pick zone that matches most ending chars
|
105
|
+
|
106
|
+
xml_str = ""
|
107
|
+
xml = Builder::XmlMarkup.new(:target=>xml_str, :indent=>2)
|
108
|
+
xml.instruct!
|
109
|
+
xml.ChangeResourceRecordSetsRequest(:xmlns => @conn.endpoint+'doc/'+@conn.api+'/') { |req|
|
110
|
+
req.ChangeBatch { |batch|
|
111
|
+
batch.Comment(comment) unless comment.nil?
|
112
|
+
batch.Changes { |changes|
|
113
|
+
change_list.each { |change_item|
|
114
|
+
change_item[:record].gen_change_xml(changes,change_item[:action])
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
#puts "XML:\n#{xml_str}" if @conn.verbose
|
120
|
+
return xml_str
|
121
|
+
end
|
122
|
+
|
123
|
+
#For modifying multiple or single records within a single transaction
|
124
|
+
def perform_actions(change_list,comment=nil)
|
125
|
+
xml_str = gen_change_xml(change_list,comment)
|
126
|
+
@conn.request(@conn.base_url + @host_url+"/rrset","POST",xml_str)
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def to_s
|
131
|
+
return "#{@name} #{@host_url}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/route53.gemspec
CHANGED
@@ -14,9 +14,16 @@ Gem::Specification.new do |s|
|
|
14
14
|
s.required_rubygems_version = ">= 1.3.5"
|
15
15
|
|
16
16
|
s.add_dependency "ruby-hmac"
|
17
|
-
s.add_dependency "
|
17
|
+
s.add_dependency "nokogiri", '~> 1.5.10'
|
18
18
|
s.add_dependency "builder"
|
19
|
-
|
19
|
+
|
20
|
+
s.add_development_dependency "rspec"
|
21
|
+
s.add_development_dependency "vcr"
|
22
|
+
s.add_development_dependency "webmock", '~> 1.15.0'
|
23
|
+
s.add_development_dependency "pry"
|
24
|
+
s.add_development_dependency "wirble"
|
25
|
+
s.add_development_dependency "rake"
|
26
|
+
|
20
27
|
s.files = `git ls-files`.split("\n")
|
21
28
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
22
29
|
s.require_path = 'lib'
|
@@ -0,0 +1,198 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: head
|
5
|
+
uri: https://route53.amazonaws.com/date
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- '*/*'
|
12
|
+
User-Agent:
|
13
|
+
- Ruby
|
14
|
+
response:
|
15
|
+
status:
|
16
|
+
code: 200
|
17
|
+
message: OK
|
18
|
+
headers:
|
19
|
+
X-Amzn-Requestid:
|
20
|
+
- 9391c336-879f-11e3-8a96-59f82340bc25
|
21
|
+
Content-Type:
|
22
|
+
- content/unknown
|
23
|
+
Content-Length:
|
24
|
+
- '2'
|
25
|
+
Date:
|
26
|
+
- Mon, 27 Jan 2014 22:08:38 GMT
|
27
|
+
body:
|
28
|
+
encoding: UTF-8
|
29
|
+
string: ''
|
30
|
+
http_version:
|
31
|
+
recorded_at: Mon, 27 Jan 2014 22:08:39 GMT
|
32
|
+
- request:
|
33
|
+
method: get
|
34
|
+
uri: https://route53.amazonaws.com/2012-12-12/hostedzone/Z3HXUG22R8JWBK?
|
35
|
+
body:
|
36
|
+
encoding: US-ASCII
|
37
|
+
string: ''
|
38
|
+
headers:
|
39
|
+
Date:
|
40
|
+
- Mon, 27 Jan 2014 22:08:38 GMT
|
41
|
+
X-Amzn-Authorization:
|
42
|
+
- AWS3-HTTPS AWSAccessKeyId=AKIAIK7CBPSH72TVCGBA,Algorithm=HmacSHA256,Signature=5iNDIpJBlCE+2sAhhanRAOsppsBpm5chQpw/DuSvwZo=
|
43
|
+
Content-Type:
|
44
|
+
- text/xml; charset=UTF-8
|
45
|
+
Accept-Encoding:
|
46
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
47
|
+
Accept:
|
48
|
+
- '*/*'
|
49
|
+
User-Agent:
|
50
|
+
- Ruby
|
51
|
+
response:
|
52
|
+
status:
|
53
|
+
code: 200
|
54
|
+
message: OK
|
55
|
+
headers:
|
56
|
+
X-Amzn-Requestid:
|
57
|
+
- 93b3ca64-879f-11e3-9add-f35e9c3aa272
|
58
|
+
Content-Type:
|
59
|
+
- text/xml
|
60
|
+
Content-Length:
|
61
|
+
- '556'
|
62
|
+
Date:
|
63
|
+
- Mon, 27 Jan 2014 22:08:39 GMT
|
64
|
+
body:
|
65
|
+
encoding: UTF-8
|
66
|
+
string: |-
|
67
|
+
<?xml version="1.0"?>
|
68
|
+
<GetHostedZoneResponse xmlns="https://route53.amazonaws.com/doc/2012-12-12/"><HostedZone><Id>/hostedzone/Z3HXUG22R8JWBK</Id><Name>50projects.com.</Name><CallerReference>a9f6b14e</CallerReference><Config/><ResourceRecordSetCount>22</ResourceRecordSetCount></HostedZone><DelegationSet><NameServers><NameServer>ns-535.awsdns-02.net</NameServer><NameServer>ns-1725.awsdns-23.co.uk</NameServer><NameServer>ns-308.awsdns-38.com</NameServer><NameServer>ns-1452.awsdns-53.org</NameServer></NameServers></DelegationSet></GetHostedZoneResponse>
|
69
|
+
http_version:
|
70
|
+
recorded_at: Mon, 27 Jan 2014 22:08:40 GMT
|
71
|
+
- request:
|
72
|
+
method: post
|
73
|
+
uri: https://route53.amazonaws.com/2012-12-12/hostedzone?
|
74
|
+
body:
|
75
|
+
encoding: UTF-8
|
76
|
+
string: |
|
77
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
78
|
+
<CreateHostedZoneRequest xmlns="https://route53.amazonaws.com/doc/2012-12-12/">
|
79
|
+
<Name>example.com.</Name>
|
80
|
+
<CallerReference>dbdc62da</CallerReference>
|
81
|
+
<HostedZoneConfig>
|
82
|
+
<Comment/>
|
83
|
+
</HostedZoneConfig>
|
84
|
+
</CreateHostedZoneRequest>
|
85
|
+
headers:
|
86
|
+
Date:
|
87
|
+
- Mon, 27 Jan 2014 22:08:38 GMT
|
88
|
+
X-Amzn-Authorization:
|
89
|
+
- AWS3-HTTPS AWSAccessKeyId=AKIAIK7CBPSH72TVCGBA,Algorithm=HmacSHA256,Signature=5iNDIpJBlCE+2sAhhanRAOsppsBpm5chQpw/DuSvwZo=
|
90
|
+
Content-Type:
|
91
|
+
- text/xml; charset=UTF-8
|
92
|
+
Accept-Encoding:
|
93
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
94
|
+
Accept:
|
95
|
+
- '*/*'
|
96
|
+
User-Agent:
|
97
|
+
- Ruby
|
98
|
+
response:
|
99
|
+
status:
|
100
|
+
code: 201
|
101
|
+
message: Created
|
102
|
+
headers:
|
103
|
+
X-Amzn-Requestid:
|
104
|
+
- 25358b9e-87a0-11e3-bf8c-1f13207fd337
|
105
|
+
Location:
|
106
|
+
- https://route53.amazonaws.com/2012-12-12//hostedzone/Z3E84CELCS8770
|
107
|
+
Content-Type:
|
108
|
+
- text/xml
|
109
|
+
Content-Length:
|
110
|
+
- '716'
|
111
|
+
Date:
|
112
|
+
- Mon, 27 Jan 2014 22:12:47 GMT
|
113
|
+
body:
|
114
|
+
encoding: UTF-8
|
115
|
+
string: |-
|
116
|
+
<?xml version="1.0"?>
|
117
|
+
<CreateHostedZoneResponse xmlns="https://route53.amazonaws.com/doc/2012-12-12/"><HostedZone><Id>/hostedzone/Z3E84CELCS8770</Id><Name>example.com.</Name><CallerReference>dbdc62da</CallerReference><Config><Comment></Comment></Config><ResourceRecordSetCount>2</ResourceRecordSetCount></HostedZone><ChangeInfo><Id>/change/C2ZW86S7M9XIU1</Id><Status>PENDING</Status><SubmittedAt>2014-01-27T22:12:47.576Z</SubmittedAt></ChangeInfo><DelegationSet><NameServers><NameServer>ns-1621.awsdns-10.co.uk</NameServer><NameServer>ns-510.awsdns-63.com</NameServer><NameServer>ns-1232.awsdns-26.org</NameServer><NameServer>ns-806.awsdns-36.net</NameServer></NameServers></DelegationSet></CreateHostedZoneResponse>
|
118
|
+
http_version:
|
119
|
+
recorded_at: Mon, 27 Jan 2014 22:12:47 GMT
|
120
|
+
- request:
|
121
|
+
method: get
|
122
|
+
uri: https://route53.amazonaws.com/2012-12-12/change/C2ZW86S7M9XIU1?
|
123
|
+
body:
|
124
|
+
encoding: US-ASCII
|
125
|
+
string: ''
|
126
|
+
headers:
|
127
|
+
Date:
|
128
|
+
- Mon, 27 Jan 2014 22:08:38 GMT
|
129
|
+
X-Amzn-Authorization:
|
130
|
+
- AWS3-HTTPS AWSAccessKeyId=AKIAIK7CBPSH72TVCGBA,Algorithm=HmacSHA256,Signature=5iNDIpJBlCE+2sAhhanRAOsppsBpm5chQpw/DuSvwZo=
|
131
|
+
Content-Type:
|
132
|
+
- text/xml; charset=UTF-8
|
133
|
+
Accept-Encoding:
|
134
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
135
|
+
Accept:
|
136
|
+
- '*/*'
|
137
|
+
User-Agent:
|
138
|
+
- Ruby
|
139
|
+
response:
|
140
|
+
status:
|
141
|
+
code: 200
|
142
|
+
message: OK
|
143
|
+
headers:
|
144
|
+
X-Amzn-Requestid:
|
145
|
+
- 278a2a47-87a0-11e3-a58f-435e724ec933
|
146
|
+
Content-Type:
|
147
|
+
- text/xml
|
148
|
+
Content-Length:
|
149
|
+
- '246'
|
150
|
+
Date:
|
151
|
+
- Mon, 27 Jan 2014 22:12:47 GMT
|
152
|
+
body:
|
153
|
+
encoding: UTF-8
|
154
|
+
string: |-
|
155
|
+
<?xml version="1.0"?>
|
156
|
+
<GetChangeResponse xmlns="https://route53.amazonaws.com/doc/2012-12-12/"><ChangeInfo><Id>/change/C2ZW86S7M9XIU1</Id><Status>PENDING</Status><SubmittedAt>2014-01-27T22:12:47.576Z</SubmittedAt></ChangeInfo></GetChangeResponse>
|
157
|
+
http_version:
|
158
|
+
recorded_at: Mon, 27 Jan 2014 22:12:48 GMT
|
159
|
+
- request:
|
160
|
+
method: delete
|
161
|
+
uri: https://route53.amazonaws.com/2012-12-12/hostedzone/Z3E84CELCS8770?
|
162
|
+
body:
|
163
|
+
encoding: US-ASCII
|
164
|
+
string: ''
|
165
|
+
headers:
|
166
|
+
Date:
|
167
|
+
- Mon, 27 Jan 2014 22:08:38 GMT
|
168
|
+
X-Amzn-Authorization:
|
169
|
+
- AWS3-HTTPS AWSAccessKeyId=AKIAIK7CBPSH72TVCGBA,Algorithm=HmacSHA256,Signature=5iNDIpJBlCE+2sAhhanRAOsppsBpm5chQpw/DuSvwZo=
|
170
|
+
Content-Type:
|
171
|
+
- text/xml; charset=UTF-8
|
172
|
+
Accept-Encoding:
|
173
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
174
|
+
Accept:
|
175
|
+
- '*/*'
|
176
|
+
User-Agent:
|
177
|
+
- Ruby
|
178
|
+
response:
|
179
|
+
status:
|
180
|
+
code: 400
|
181
|
+
message: Bad Request
|
182
|
+
headers:
|
183
|
+
X-Amzn-Requestid:
|
184
|
+
- 8f57cd8b-87a0-11e3-b239-49b331f5c62c
|
185
|
+
Content-Type:
|
186
|
+
- text/xml
|
187
|
+
Content-Length:
|
188
|
+
- '348'
|
189
|
+
Date:
|
190
|
+
- Mon, 27 Jan 2014 22:15:41 GMT
|
191
|
+
body:
|
192
|
+
encoding: UTF-8
|
193
|
+
string: |-
|
194
|
+
<?xml version="1.0"?>
|
195
|
+
<ErrorResponse xmlns="https://route53.amazonaws.com/doc/2012-12-12/"><Error><Type>Sender</Type><Code>RequestExpired</Code><Message>Request timestamp: Mon, 27 Jan 2014 22:08:38 GMT expired. It must be within 300 secs/ of server time.</Message></Error><RequestId>8f57cd8b-87a0-11e3-b239-49b331f5c62c</RequestId></ErrorResponse>
|
196
|
+
http_version:
|
197
|
+
recorded_at: Mon, 27 Jan 2014 22:15:42 GMT
|
198
|
+
recorded_with: VCR 2.8.0
|