dns-zonefile 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ module DNS
2
+ module Zonefile
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -8,12 +8,8 @@ describe "DNS::Zonefile" do
8
8
  }.should_not raise_error
9
9
  end
10
10
 
11
- it "should be version 0.0.1" do
12
- DNS::Zonefile::VERSION.should eql("0.0.1")
13
- end
14
-
15
- it "should have an origin" do
16
- DNS::Zonefile.new.should respond_to(:origin)
11
+ it "should be version 1.0.0" do
12
+ DNS::Zonefile::VERSION.should eql("1.0.0")
17
13
  end
18
14
 
19
15
  it "should provide a way of parsing a string" do
@@ -26,33 +22,78 @@ describe "DNS::Zonefile" do
26
22
  ; Hi! I'm an example zonefile.
27
23
  $ORIGIN example.com.
28
24
  $TTL 86400; expire in 1 day.
25
+ $OTHER abc
26
+ ; line above has spaces at the end, but no comment
29
27
  @ IN SOA ns.example.com. hostmaster.example.com. (
30
28
  2007120710 ; serial number of this zone file
31
29
  1d ; slave refresh (1 day)
32
30
  1d ; slave retry time in case of a problem (1 day)
33
- 4w ; slave expiration time (4 weeks)
34
- 1h ; minimum caching time in case of failed lookups (1 hour)
31
+ 4W ; slave expiration time (4 weeks)
32
+ 3600 ; minimum caching time in case of failed lookups (1 hour)
35
33
  )
36
34
  ; That's the SOA part done.
37
35
 
36
+ ; Next comment line has nothing after the semi-colon.
37
+ ;
38
+
38
39
  ; Let's start the resource records.
39
40
  example.com. NS ns ; ns.example.com is the nameserver for example.com
40
- example.com. NS ns.somewhere.com. ; ns.somewhere.com is a backup nameserver for example.co
41
- example.com. A 10.0.0.1 ; ip address for "example.com"
41
+ example.com. NS ns.somewhere.com. ; ns.somewhere.com is a backup nameserver for example.com
42
+ example.com. A 10.0.0.1 ; ip address for "example.com". next line has spaces after the IP, but no actual comment.
43
+ @ A 10.0.0.11
44
+ A 10.0.0.12 ; tertiary ip for "example.com"
42
45
  ns A 10.0.0.2 ; ip address for "ns.example.com"
46
+ 60 A 10.0.0.21 ; secondary ip for "ns.example.com" with TTL
47
+ * A 10.0.0.100 ; wildcard
48
+ *.sub A 10.0.0.101 ; subdomain wildcard
49
+ with-class IN A 10.0.0.3 ; record that includes the class type of IN
50
+ with-ttl 60 A 10.0.0.5 ; with a specified TTL
51
+ ttl-class 60 IN A 10.0.0.6 ; with TTL and class type
43
52
  www CNAME ns ; "www.example.com" is an alias for "ns.example.com"
44
53
  wwwtest CNAME www ; "wwwtest.example.com" is another alias for "www.example.com"
54
+ www2 CNAME ns.example.com. ; yet another alias, with FQDN target
45
55
 
46
56
  ; Email... that'll be fun then
47
57
  example.com. MX 10 mail.example.com. ; mail.example.com is the mailserver for example.com
48
58
  @ MX 20 mail2.example.com. ; Similar to above line, but using "@" to say "use $ORIGIN"
49
59
  @ MX 50 mail3 ; Similar to above line, but using a host within this domain
60
+
61
+ @ AAAA 2001:db8:a::1 ; IPv6, lowercase
62
+ ns AAAA 2001:DB8:B::1 ; IPv6, uppercase
63
+ mail AAAA 2001:db8:c::10.0.0.4 ; IPv6, with trailing IPv4-type address
64
+
65
+ sip NAPTR 100 10 "U" "E2U+sip" "!^.*$!sip:cs@example.com!i" . ; NAPTR record
66
+ sip2 NAPTR 100 10 "" "" "/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i" . ; another one
67
+
68
+ _xmpp-server._tcp SRV 5 0 5269 xmpp-server.l.google.com. ; SRV record
69
+
70
+ ; TXT record, with embedded semicolons
71
+ _domainkey TXT "v=DKIM1\\;g=*\\;k=rsa\\; p=4tkw1bbkfa0ahfjgnbewr2ttkvahvfmfizowl9s4g0h28io76ndow25snl9iumpcv0jwxr2k"
72
+
73
+ @ TXT "some other \\"message\\" goes here" ; embedded quotes
74
+ long TXT "a multi-segment TXT record" "usually used for really long TXT records" "since each segment can only span 255 chars"
75
+ unquoted TXT some text data
76
+ @ SPF "v=spf1 a a:other.domain.com ~all"
77
+
78
+ 45 IN PTR @
79
+
80
+ $ORIGIN test.example.com.
81
+ $TTL 3600; expire in 1 day.
82
+ @ A 10.1.0.1 ; Test with alternate origin
83
+ MX 10 mail.example.com.
84
+ www A 10.1.0.2 ; www.test.example.com.
85
+
50
86
  ZONE
51
87
  end
52
88
 
53
89
  it "should set the origin correctly" do
54
90
  zone = DNS::Zonefile.parse(@zonefile)
55
- zone.origin.should eql('example.com.')
91
+ zone.origin.should eql('@')
92
+ end
93
+
94
+ it "should interpret the origin correctly" do
95
+ zone = DNS::Zonefile.load(@zonefile)
96
+ zone.soa.origin.should eql('example.com.')
56
97
  end
57
98
 
58
99
  it "should set the zone variables correctly" do
@@ -61,81 +102,240 @@ ZONE
61
102
  zone.variables['ORIGIN'].should eql('example.com.')
62
103
  end
63
104
 
64
- it "should set the SOA correctly" do
65
- zone = DNS::Zonefile.parse(@zonefile)
105
+ it "should interpret the SOA correctly" do
106
+ zone = DNS::Zonefile.load(@zonefile)
66
107
  soa = zone.soa
67
- soa.ns.to_s.should eql('ns.example.com.')
68
- soa.rp.to_s.should eql('hostmaster.example.com.')
69
- soa.serial.to_i.should eql(2007120710)
70
- soa.refresh.to_i.should eql(86400)
71
- soa.retry.to_i.should eql(86400)
72
- soa.expiry.to_i.should eql(2419200)
73
- soa.ttl.to_i.should eql(3600)
108
+ soa.klass.should eql('IN')
109
+ soa.ttl.should eql(86400)
110
+ soa.nameserver.should eql('ns.example.com.')
111
+ soa.responsible_party.should eql('hostmaster.example.com.')
112
+ soa.serial.should eql(2007120710)
113
+ soa.refresh_time.should eql(86400)
114
+ soa.retry_time.should eql(86400)
115
+ soa.expiry_time.should eql(2419200)
116
+ soa.nxttl.should eql(3600)
74
117
  end
75
118
 
76
119
  it "should build the correct number of resource records" do
77
120
  zone = DNS::Zonefile.parse(@zonefile)
78
- zone.rr.size.should be(9)
121
+ zone.rr.size.should be(33)
79
122
  end
80
123
 
81
124
  it "should build the correct NS records" do
82
- zone = DNS::Zonefile.parse(@zonefile)
83
- ns_records = zone.rr.select { |rr| rr.record_type == "NS" }
125
+ zone = DNS::Zonefile.load(@zonefile)
126
+ ns_records = zone.records_of DNS::Zonefile::NS
84
127
  ns_records.size.should be(2)
85
128
 
86
129
  ns_records.detect { |ns|
87
- ns.host.to_s == "example.com." && ns.nameserver.to_s == "ns.example.com."
130
+ ns.host == "example.com." && ns.nameserver == "ns.example.com."
88
131
  }.should_not be_nil
89
132
 
90
133
  ns_records.detect { |ns|
91
- ns.host.to_s == "example.com." && ns.nameserver.to_s == "ns.somewhere.com."
134
+ ns.host == "example.com." && ns.nameserver == "ns.somewhere.com." && ns.ttl == 86400
92
135
  }.should_not be_nil
93
136
  end
94
137
 
95
138
  it "should build the correct A records" do
96
- zone = DNS::Zonefile.parse(@zonefile)
97
- a_records = zone.rr.select { |rr| rr.record_type == "A" }
98
- a_records.size.should be(2)
139
+ zone = DNS::Zonefile.load(@zonefile)
140
+ a_records = zone.records_of DNS::Zonefile::A
141
+ a_records.size.should be(12)
142
+
143
+ a_records.detect { |a|
144
+ a.host == "example.com." && a.address == "10.0.0.1"
145
+ }.should_not be_nil
146
+
147
+ a_records.detect { |a|
148
+ a.host == "example.com." && a.address == "10.0.0.11"
149
+ }.should_not be_nil
150
+
151
+ a_records.detect { |a|
152
+ a.host == "example.com." && a.address == "10.0.0.12"
153
+ }.should_not be_nil
99
154
 
100
155
  a_records.detect { |a|
101
- a.host.to_s == "example.com." && a.ip_address.to_s == "10.0.0.1"
156
+ a.host == "ns.example.com." && a.address == "10.0.0.2" && a.ttl == 86400
102
157
  }.should_not be_nil
103
158
 
104
159
  a_records.detect { |a|
105
- a.host.to_s == "ns.example.com." && a.ip_address.to_s == "10.0.0.2"
160
+ a.host == "ns.example.com." && a.address == "10.0.0.21" && a.ttl == 60
161
+ }.should_not be_nil
162
+
163
+ a_records.detect { |a|
164
+ a.host == "*.example.com." && a.address == "10.0.0.100"
165
+ }.should_not be_nil
166
+
167
+ a_records.detect { |a|
168
+ a.host == "*.sub.example.com." && a.address == "10.0.0.101"
169
+ }.should_not be_nil
170
+
171
+ a_records.detect { |a|
172
+ a.host == "with-class.example.com." && a.address == "10.0.0.3" && a.ttl == 86400
173
+ }.should_not be_nil
174
+
175
+ a_records.detect { |a|
176
+ a.host == "with-ttl.example.com." && a.address == "10.0.0.5" && a.ttl == 60
177
+ }.should_not be_nil
178
+
179
+ a_records.detect { |a|
180
+ a.host == "ttl-class.example.com." && a.address == "10.0.0.6" && a.ttl == 60
181
+ }.should_not be_nil
182
+
183
+ a_records.detect { |a|
184
+ a.host == "test.example.com." && a.address == "10.1.0.1" && a.ttl == 3600
185
+ }.should_not be_nil
186
+
187
+ a_records.detect { |a|
188
+ a.host == "www.test.example.com." && a.address == "10.1.0.2" && a.ttl == 3600
106
189
  }.should_not be_nil
107
190
  end
108
191
 
109
192
  it "should build the correct CNAME records" do
110
- zone = DNS::Zonefile.parse(@zonefile)
111
- cname_records = zone.rr.select { |rr| rr.record_type == "CNAME" }
112
- cname_records.size.should be(2)
193
+ zone = DNS::Zonefile.load(@zonefile)
194
+ cname_records = zone.records_of DNS::Zonefile::CNAME
195
+ cname_records.size.should be(3)
196
+
197
+ cname_records.detect { |cname|
198
+ cname.host == "www.example.com." && cname.target == "ns.example.com."
199
+ }.should_not be_nil
113
200
 
114
201
  cname_records.detect { |cname|
115
- cname.alias.to_s == "www.example.com." && cname.host.to_s == "ns.example.com."
202
+ cname.host == "wwwtest.example.com." && cname.domainname == "www.example.com."
116
203
  }.should_not be_nil
117
204
 
118
205
  cname_records.detect { |cname|
119
- cname.alias.to_s == "wwwtest.example.com." && cname.host.to_s == "www.example.com."
206
+ cname.host == "www2.example.com." && cname.domainname == "ns.example.com." && cname.ttl == 86400
120
207
  }.should_not be_nil
121
208
  end
122
209
 
123
210
  it "should build the correct MX records" do
124
- zone = DNS::Zonefile.parse(@zonefile)
125
- mx_records = zone.rr.select { |rr| rr.record_type == "MX" }
126
- mx_records.size.should be(3)
211
+ zone = DNS::Zonefile.load(@zonefile)
212
+ mx_records = zone.records_of DNS::Zonefile::MX
213
+ mx_records.size.should be(4)
214
+
215
+ mx_records.detect { |mx|
216
+ mx.host == "example.com." && mx.priority == 10 && mx.exchanger == 'mail.example.com.'
217
+ }.should_not be_nil
127
218
 
128
219
  mx_records.detect { |mx|
129
- mx.host.to_s == "example.com." && mx.priority.to_i == 10 && mx.exchanger.to_s == 'mail.example.com.'
220
+ mx.host == "example.com." && mx.priority == 20 && mx.exchange == 'mail2.example.com.'
130
221
  }.should_not be_nil
131
222
 
132
223
  mx_records.detect { |mx|
133
- mx.host.to_s == "example.com." && mx.priority.to_i == 20 && mx.exchanger.to_s == 'mail2.example.com.'
224
+ mx.host == "example.com." && mx.priority == 50 && mx.domainname == 'mail3.example.com.' && mx.ttl == 86400
134
225
  }.should_not be_nil
135
226
 
136
227
  mx_records.detect { |mx|
137
- mx.host.to_s == "example.com." && mx.priority.to_i == 50 && mx.exchanger.to_s == 'mail3.example.com.'
228
+ mx.host == "test.example.com." && mx.priority == 10 && mx.domainname == 'mail.example.com.' && mx.ttl == 3600
229
+ }.should_not be_nil
230
+ end
231
+
232
+ it "should build the correct AAAA records" do
233
+ zone = DNS::Zonefile.load(@zonefile)
234
+ aaaa_records = zone.records_of DNS::Zonefile::AAAA
235
+ aaaa_records.size.should be(3)
236
+
237
+ aaaa_records.detect { |a|
238
+ a.host == "example.com." && a.address == "2001:db8:a::1"
239
+ }.should_not be_nil
240
+
241
+ aaaa_records.detect { |a|
242
+ a.host == "ns.example.com." && a.address == "2001:db8:b::1"
243
+ }.should_not be_nil
244
+
245
+ aaaa_records.detect { |a|
246
+ a.host == "mail.example.com." && a.address == "2001:db8:c::10.0.0.4" && a.ttl == 86400
247
+ }.should_not be_nil
248
+ end
249
+
250
+ it "should build the correct NAPTR records" do
251
+ zone = DNS::Zonefile.load(@zonefile)
252
+ naptr_records = zone.records_of DNS::Zonefile::NAPTR
253
+ naptr_records.size.should be(2)
254
+
255
+ naptr_records.detect { |r|
256
+ r.host == "sip.example.com." && r.data == '100 10 "U" "E2U+sip" "!^.*$!sip:cs@example.com!i" .'
257
+ }.should_not be_nil
258
+
259
+ naptr_records.detect { |r|
260
+ r.host == "sip2.example.com." && r.data == %q{100 10 "" "" "/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i" .} && r.ttl == 86400
261
+ }.should_not be_nil
262
+ end
263
+
264
+ it "should build the correct SRV records" do
265
+ zone = DNS::Zonefile.load(@zonefile)
266
+ srv_records = zone.records_of DNS::Zonefile::SRV
267
+ srv_records.size.should be(1)
268
+
269
+ srv_records.detect { |r|
270
+ r.host == "_xmpp-server._tcp.example.com." && r.priority == 5 && r.weight == 0 && r.port == 5269 && r.target == 'xmpp-server.l.google.com.' && r.ttl == 86400
271
+ }.should_not be_nil
272
+ end
273
+
274
+ it "should build the correct TXT records" do
275
+ zone = DNS::Zonefile.load(@zonefile)
276
+ txt_records = zone.records_of DNS::Zonefile::TXT
277
+ txt_records.size.should be(4)
278
+
279
+ txt_records.detect { |r|
280
+ r.host == "_domainkey.example.com." && r.data == '"v=DKIM1\;g=*\;k=rsa\; p=4tkw1bbkfa0ahfjgnbewr2ttkvahvfmfizowl9s4g0h28io76ndow25snl9iumpcv0jwxr2k"'
281
+ }.should_not be_nil
282
+
283
+ txt_records.detect { |r|
284
+ r.host == "example.com." && r.data == '"some other \"message\" goes here"' && r.ttl == 86400
285
+ }.should_not be_nil
286
+
287
+ txt_records.detect { |r|
288
+ r.host == "long.example.com." && r.data == '"a multi-segment TXT record" "usually used for really long TXT records" "since each segment can only span 255 chars"'
289
+ }.should_not be_nil
290
+
291
+ txt_records.detect { |r|
292
+ r.host == "unquoted.example.com." && r.data == 'some text data'
138
293
  }.should_not be_nil
139
294
  end
295
+
296
+ it "should build the correct SPF records" do
297
+ zone = DNS::Zonefile.load(@zonefile)
298
+ spf_records = zone.records_of DNS::Zonefile::SPF
299
+ spf_records.size.should be(1)
300
+
301
+ spf_records.detect { |r|
302
+ r.host == "example.com." && r.data == '"v=spf1 a a:other.domain.com ~all"' && r.ttl == 86400
303
+ }.should_not be_nil
304
+ end
305
+
306
+ it "should build the correct PTR records" do
307
+ zone = DNS::Zonefile.load(@zonefile)
308
+ ptr_records = zone.records_of DNS::Zonefile::PTR
309
+ ptr_records.size.should be(1)
310
+
311
+ ptr_records.detect { |r|
312
+ r.host == "45.example.com." && r.target == 'example.com.' && r.ttl == 86400
313
+ }.should_not be_nil
314
+ end
315
+ end
316
+
317
+ describe "parsing an SOA without parens" do
318
+ before(:each) do
319
+ @zonefile =<<-ZONE
320
+ example.com. 86400 IN SOA ns0.example.com. hostmaster.example.com. 2006010558 43200 3600 1209600 180
321
+ example.com. 3600 IN A 1.2.3.4
322
+ example.com. 86400 IN SOA ns0.example.com. hostmaster.example.com. 2006010558 43200 3600 1209600 180
323
+
324
+ ZONE
325
+ end
326
+
327
+ it "should parse the SOA record correctly" do
328
+ zone = DNS::Zonefile.load(@zonefile)
329
+ soa = zone.soa
330
+ soa.klass.should eql('IN')
331
+ soa.ttl.should eql(86400)
332
+ soa.nameserver.should eql('ns0.example.com.')
333
+ soa.responsible_party.should eql('hostmaster.example.com.')
334
+ soa.serial.should eql(2006010558)
335
+ soa.refresh_time.should eql(43200)
336
+ soa.retry_time.should eql(3600)
337
+ soa.expiry_time.should eql(1209600)
338
+ soa.nxttl.should eql(180)
339
+ end
140
340
  end
141
341
  end
@@ -1,2 +1,2 @@
1
- require 'spec'
2
- require 'dns/zonefile'
1
+ require 'rspec'
2
+ require 'dns/zonefile'
metadata CHANGED
@@ -1,72 +1,101 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: dns-zonefile
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
5
6
  platform: ruby
6
- authors:
7
+ authors:
7
8
  - Craig R Webster
8
- autorequire: dns/zonefile
9
+ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
-
12
- date: 2010-01-13 00:00:00 +00:00
13
- default_executable:
14
- dependencies: []
15
-
16
- description: Parse and manipulate with DNS zonefiles. Great for working with BIND.
17
- email: craig@barkingiguana.com
12
+ date: 2011-10-26 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70265569399900 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - =
20
+ - !ruby/object:Gem::Version
21
+ version: '2.6'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70265569399900
25
+ - !ruby/object:Gem::Dependency
26
+ name: treetop
27
+ requirement: &70265569399480 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70265569399480
36
+ - !ruby/object:Gem::Dependency
37
+ name: polyglot
38
+ requirement: &70265569399020 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70265569399020
47
+ description: ! "The format of a DNS Zonefile is defined in RFC 1035 section 5 and
48
+ RFC\n1034 section 3.6.1. To anyone who's using BIND they'll look very \nfamiliar.\n\nThis
49
+ is an attempt to use Ruby parse them into an object graph which can \nbe investigated
50
+ programatically, manipulated, validated or printed into \nsome canonical form."
51
+ email:
52
+ - craig@barkingiguana.com
18
53
  executables: []
19
-
20
54
  extensions: []
21
-
22
- extra_rdoc_files:
23
- - Rakefile
55
+ extra_rdoc_files: []
56
+ files:
57
+ - .gitignore
58
+ - Gemfile
59
+ - Gemfile.lock
60
+ - LICENCE
24
61
  - README
62
+ - Rakefile
25
63
  - TODO
64
+ - dns-zonefile.gemspec
65
+ - doc/example.com.zone
26
66
  - doc/example2.com.zone
27
67
  - doc/example3.com.zone
28
68
  - doc/zonefile.example
29
69
  - doc/zonefile.treetop
30
- files:
31
70
  - lib/dns/zonefile.rb
32
- - lib/dns/zonefile_parser.rb
71
+ - lib/dns/zonefile/parser.rb
72
+ - lib/dns/zonefile/version.rb
33
73
  - spec/dns/zonefile_spec.rb
34
74
  - spec/spec_helper.rb
35
- - Rakefile
36
- - README
37
- - TODO
38
- - doc/example2.com.zone
39
- - doc/example3.com.zone
40
- - doc/zonefile.example
41
- - doc/zonefile.treetop
42
- has_rdoc: true
43
- homepage: http://barkingiguana.com/
75
+ homepage: ''
44
76
  licenses: []
45
-
46
77
  post_install_message:
47
- rdoc_options:
48
- - --title
49
- - DNS::Zonefile -- Work with zonefiles
50
- require_paths:
78
+ rdoc_options: []
79
+ require_paths:
51
80
  - lib
52
- required_ruby_version: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: "0"
57
- version:
58
- required_rubygems_version: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: "0"
63
- version:
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
64
93
  requirements: []
65
-
66
- rubyforge_project:
67
- rubygems_version: 1.3.5
94
+ rubyforge_project: dns-zonefile
95
+ rubygems_version: 1.8.10
68
96
  signing_key:
69
97
  specification_version: 3
70
- summary: Parse and manipulate with DNS zonefiles.
71
- test_files: []
72
-
98
+ summary: Work with zonefiles (RFC 1035 section 5 and RFC 1034 section 3.6.1)
99
+ test_files:
100
+ - spec/dns/zonefile_spec.rb
101
+ - spec/spec_helper.rb