dns-zone 0.0.0.alpha → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY.md +6 -0
- data/README.md +30 -16
- data/dns-zone.gemspec +9 -9
- data/lib/dns/zone.rb +15 -3
- data/lib/dns/zone/rr.rb +18 -8
- data/lib/dns/zone/rr/a.rb +1 -1
- data/lib/dns/zone/rr/cname.rb +8 -1
- data/lib/dns/zone/rr/hinfo.rb +35 -0
- data/lib/dns/zone/rr/mx.rb +20 -3
- data/lib/dns/zone/rr/ns.rb +1 -1
- data/lib/dns/zone/rr/ptr.rb +21 -0
- data/lib/dns/zone/rr/record.rb +5 -5
- data/lib/dns/zone/rr/soa.rb +10 -11
- data/lib/dns/zone/rr/spf.rb +5 -0
- data/lib/dns/zone/rr/srv.rb +23 -2
- data/lib/dns/zone/rr/txt.rb +2 -2
- data/lib/dns/zone/test_case.rb +0 -1
- data/lib/dns/zone/version.rb +1 -1
- data/test/rr/a_test.rb +6 -5
- data/test/rr/aaaa_test.rb +15 -1
- data/test/rr/cname_test.rb +8 -1
- data/test/rr/hinfo_test.rb +44 -0
- data/test/rr/mx_test.rb +13 -5
- data/test/rr/ns_test.rb +8 -1
- data/test/rr/ptr_test.rb +19 -0
- data/test/rr/record_test.rb +10 -3
- data/test/rr/soa_test.rb +4 -4
- data/test/rr/spf_test.rb +20 -0
- data/test/rr/srv_test.rb +11 -1
- data/test/rr/txt_test.rb +4 -4
- data/test/zone_test.rb +101 -30
- metadata +26 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3052117b3384d87298a0e7d5cd4c1b34d7ef4f6c
|
4
|
+
data.tar.gz: cff80132cb642fdd37318ca8dd80f3e91d2281a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd218bbea886f9a87aa8e1bba28f13434bf07552871b5467952d932d8a13be2d409c0e5046dcd6779430b3ea33fc90f5a9af202d34552f821e62b572be354f07
|
7
|
+
data.tar.gz: 55a0d835cff7186e60c876ae07d8ed4dab474c12b8388168ac63d0bc5c13f75f2cc26adba9060e068a98e7ab79adc56cc673b4722763b0d74556aa0699475784
|
data/HISTORY.md
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
dns-zone
|
2
2
|
========
|
3
3
|
|
4
|
+
[](http://travis-ci.org/lantins/dns-zone)
|
5
|
+
[](http://badge.fury.io/rb/dns-zone)
|
6
|
+
|
4
7
|
A Ruby library for building and parsing DNS zone files.
|
5
8
|
|
6
9
|
## Installation
|
@@ -19,21 +22,20 @@ Require the gem in your code:
|
|
19
22
|
|
20
23
|
## Usage
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
DNS::Zone
|
25
|
-
|
25
|
+
### Loading a zone file
|
26
|
+
|
27
|
+
zone = DNS::Zone.load(zone_as_string)
|
28
|
+
|
29
|
+
### Creating a new zone programmatically
|
26
30
|
|
27
31
|
zone = DNS::Zone.new
|
28
32
|
zone.origin = 'example.com.'
|
29
|
-
# FIXME: not sure what RFC (if any) defines the time formatting
|
30
33
|
zone.ttl = '1d'
|
31
|
-
# FIXME: keep DNS style representation? for <domain-name>s and email addresses
|
32
34
|
zone.soa.nameserver = 'ns0.lividpenguin.com.'
|
33
35
|
zone.soa.email = 'hostmaster.lividpenguin.com.'
|
34
36
|
|
35
37
|
# output as dns zone file
|
36
|
-
zone.
|
38
|
+
zone.dump
|
37
39
|
|
38
40
|
# Development
|
39
41
|
|
@@ -55,30 +57,42 @@ Require the gem in your code:
|
|
55
57
|
|
56
58
|
## Must have
|
57
59
|
|
58
|
-
[
|
60
|
+
[x] Ability to load a zone made of multiple RR's
|
59
61
|
[x] Add support for RR Type: SOA
|
60
|
-
[
|
61
|
-
[
|
62
|
-
[
|
63
|
-
[
|
62
|
+
[x] Add support for RR Type: NS
|
63
|
+
[x] Add support for RR Type: MX
|
64
|
+
[x] Add support for RR Type: AAAA
|
65
|
+
[x] Add support for RR Type: A
|
66
|
+
[x] Add support for RR Type: CNAME
|
67
|
+
[x] Add support for RR Type: TXT
|
68
|
+
[x] Add support for RR Type: SRV
|
69
|
+
[x] Add support for RR Type: PTR
|
70
|
+
[x] Add support for RR Type: SPF
|
71
|
+
[x] Add support for RR Type: HINFO
|
72
|
+
[x] Support loading zone where some records have an empty label
|
64
73
|
|
65
74
|
## Would be nice
|
66
75
|
|
67
76
|
[ ] Handle parsing a zone file that uses more then one $ORIGIN directive.
|
68
|
-
[ ]
|
77
|
+
[ ] Basic validation, error checking:
|
69
78
|
[ ] Only one SOA per zone.
|
70
79
|
[ ] CNAMEs can't use a label of `@`.
|
80
|
+
[ ] PTR zones have some extra conditions:
|
81
|
+
[ ] labels cant be repeted
|
82
|
+
[ ] names should end in a dot, otherwise they are invalid after expansion
|
83
|
+
[ ] IPv4 and IPv6 cant be mixed
|
71
84
|
|
72
85
|
[ ] Ability to 'include' defaults/records into a zone.
|
73
|
-
This may or may not
|
86
|
+
This may or may not mean supporting the `$INCLUDE` directive.
|
74
87
|
|
75
88
|
## At some point; low priority
|
76
89
|
|
77
90
|
[ ] Configuration options:
|
78
91
|
[ ] spaces/tabs used between RR params in zone file output
|
79
|
-
[ ] time format
|
80
|
-
|
92
|
+
[ ] time format used in output (should parse both formats, seconds or bind time format (e.g. 1d))
|
93
|
+
[ ] add comments to explain TTL's that are in seconds
|
81
94
|
[ ] Ability to add comment to RR (n.b. currently we strip comments when parsing)
|
95
|
+
[ ] Add support for RR Type: LOC (RFC 1876)
|
82
96
|
[ ] Add support for RR Type: DNAME
|
83
97
|
[ ] Add support for RR Type: DNSKEY
|
84
98
|
[ ] Add support for RR Type: DS
|
data/dns-zone.gemspec
CHANGED
@@ -24,18 +24,18 @@ spec = Gem::Specification.new do |s|
|
|
24
24
|
# cross platform gem dependencies
|
25
25
|
#s.add_dependency('gli')
|
26
26
|
#s.add_dependency('paint')
|
27
|
-
s.add_development_dependency('bundler',
|
28
|
-
s.add_development_dependency('rake',
|
29
|
-
s.add_development_dependency('minitest',
|
30
|
-
s.add_development_dependency('simplecov',
|
31
|
-
s.add_development_dependency('yard',
|
32
|
-
s.add_development_dependency('inch',
|
33
|
-
s.add_development_dependency('guard-minitest', '~> 0')
|
34
|
-
s.add_development_dependency('guard-bundler',
|
27
|
+
s.add_development_dependency('bundler', '~> 1.0')
|
28
|
+
s.add_development_dependency('rake', '>= 9.0')
|
29
|
+
s.add_development_dependency('minitest', '~> 5.0')
|
30
|
+
s.add_development_dependency('simplecov', '~> 0.7.1')
|
31
|
+
s.add_development_dependency('yard', '~> 0.8')
|
32
|
+
s.add_development_dependency('inch', '~> 0.3')
|
33
|
+
s.add_development_dependency('guard-minitest', '~> 2.0')
|
34
|
+
s.add_development_dependency('guard-bundler', '~> 0')
|
35
35
|
|
36
36
|
# long description.
|
37
37
|
s.description = <<-EOL
|
38
38
|
A Ruby library for building and parsing DNS zone files for use with
|
39
39
|
Bind and PowerDNS (with Bind backend) DNS servers.
|
40
40
|
EOL
|
41
|
-
end
|
41
|
+
end
|
data/lib/dns/zone.rb
CHANGED
@@ -15,6 +15,15 @@ module DNS
|
|
15
15
|
@records = []
|
16
16
|
end
|
17
17
|
|
18
|
+
def dump
|
19
|
+
content = []
|
20
|
+
@records.each do |rr|
|
21
|
+
content << rr.dump
|
22
|
+
end
|
23
|
+
|
24
|
+
content.join("\n") << "\n"
|
25
|
+
end
|
26
|
+
|
18
27
|
# FROM RFC:
|
19
28
|
# The format of these files is a sequence of entries. Entries are
|
20
29
|
# predominantly line-oriented, though parentheses can be used to continue
|
@@ -30,6 +39,7 @@ module DNS
|
|
30
39
|
|
31
40
|
instance = self.new
|
32
41
|
|
42
|
+
options = {}
|
33
43
|
entries.each do |entry|
|
34
44
|
if entry =~ /\$(ORIGIN|TTL)\s+(.+)/
|
35
45
|
instance.ttl = $2 if $1 == 'TTL'
|
@@ -37,9 +47,11 @@ module DNS
|
|
37
47
|
next
|
38
48
|
end
|
39
49
|
|
40
|
-
if entry =~ DNS::Zone::RR::
|
41
|
-
rec = DNS::Zone::RR.load(entry)
|
42
|
-
|
50
|
+
if entry =~ DNS::Zone::RR::REGEX_RR
|
51
|
+
rec = DNS::Zone::RR.load(entry, options)
|
52
|
+
next unless rec
|
53
|
+
instance.records << rec
|
54
|
+
options[:last_label] = rec.label
|
43
55
|
end
|
44
56
|
|
45
57
|
end
|
data/lib/dns/zone/rr.rb
CHANGED
@@ -5,11 +5,12 @@ module DNS
|
|
5
5
|
# The #{load} method will convert RR string data into a Ruby class.
|
6
6
|
module RR
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
REGEX_TTL = /\d+[wdmhs]?/i
|
9
|
+
REGEX_KLASS = /(?<klass>IN)?/i
|
10
|
+
REGEX_TYPE = /(?<type>A|AAAA|CNAME|HINFO|MX|NS|SOA|SPF|SRV|TXT|PTR)\s{1}/i
|
11
|
+
REGEX_RR = /^(?<label>\S+|\s{1})\s*(?<ttl>#{REGEX_TTL})?\s*#{REGEX_KLASS}\s*#{REGEX_TYPE}\s*(?<rdata>[\s\S]*)$/i
|
12
|
+
REGEX_DOMAINNAME = /\S+\./i
|
13
|
+
REGEX_STRING = /((?:[^"\\]+|\\.)*)/
|
13
14
|
|
14
15
|
# Load RR string data and return an instance representing the RR.
|
15
16
|
#
|
@@ -21,15 +22,21 @@ module DNS
|
|
21
22
|
# strip comments, unless its escaped.
|
22
23
|
string.gsub!(/(?<!\\);.*/o, "");
|
23
24
|
|
24
|
-
captures = string.match(
|
25
|
+
captures = string.match(REGEX_RR)
|
25
26
|
return nil unless captures
|
26
27
|
|
27
28
|
case captures[:type]
|
28
29
|
when 'A' then A.new.load(string, options)
|
29
30
|
when 'AAAA' then AAAA.new.load(string, options)
|
30
|
-
when '
|
31
|
-
when '
|
31
|
+
when 'CNAME' then CNAME.new.load(string, options)
|
32
|
+
when 'HINFO' then HINFO.new.load(string, options)
|
33
|
+
when 'MX' then MX.new.load(string, options)
|
32
34
|
when 'NS' then NS.new.load(string, options)
|
35
|
+
when 'PTR' then PTR.new.load(string, options)
|
36
|
+
when 'SOA' then SOA.new.load(string, options)
|
37
|
+
when 'SPF' then SPF.new.load(string, options)
|
38
|
+
when 'SRV' then SRV.new.load(string, options)
|
39
|
+
when 'TXT' then TXT.new.load(string, options)
|
33
40
|
else
|
34
41
|
raise 'Unknown RR Type'
|
35
42
|
end
|
@@ -40,9 +47,12 @@ module DNS
|
|
40
47
|
autoload :A, 'dns/zone/rr/a'
|
41
48
|
autoload :AAAA, 'dns/zone/rr/aaaa'
|
42
49
|
autoload :CNAME, 'dns/zone/rr/cname'
|
50
|
+
autoload :HINFO, 'dns/zone/rr/hinfo'
|
43
51
|
autoload :MX, 'dns/zone/rr/mx'
|
44
52
|
autoload :NS, 'dns/zone/rr/ns'
|
53
|
+
autoload :PTR, 'dns/zone/rr/ptr'
|
45
54
|
autoload :SOA, 'dns/zone/rr/soa'
|
55
|
+
autoload :SPF, 'dns/zone/rr/spf'
|
46
56
|
autoload :SRV, 'dns/zone/rr/srv'
|
47
57
|
autoload :TXT, 'dns/zone/rr/txt'
|
48
58
|
end
|
data/lib/dns/zone/rr/a.rb
CHANGED
data/lib/dns/zone/rr/cname.rb
CHANGED
@@ -5,10 +5,17 @@ class DNS::Zone::RR::CNAME < DNS::Zone::RR::Record
|
|
5
5
|
|
6
6
|
attr_accessor :domainname
|
7
7
|
|
8
|
-
def
|
8
|
+
def dump
|
9
9
|
parts = general_prefix
|
10
10
|
parts << domainname
|
11
11
|
parts.join(' ')
|
12
12
|
end
|
13
13
|
|
14
|
+
def load(string, options = {})
|
15
|
+
rdata = load_general_and_get_rdata(string, options)
|
16
|
+
return nil unless rdata
|
17
|
+
@domainname = rdata
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
14
21
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# `HINFO` resource record.
|
2
|
+
#
|
3
|
+
# RFC 1035
|
4
|
+
class DNS::Zone::RR::HINFO < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_QUOTES_OPTIONAL = %r{
|
7
|
+
"#{DNS::Zone::RR::REGEX_STRING}"|#{DNS::Zone::RR::REGEX_STRING}
|
8
|
+
}mx
|
9
|
+
|
10
|
+
REGEX_HINFO_RDATA = %r{
|
11
|
+
(?<cpu>(?:#{REGEX_QUOTES_OPTIONAL})){1}\s
|
12
|
+
(?<os>(?:#{REGEX_QUOTES_OPTIONAL})){1}
|
13
|
+
}mx
|
14
|
+
attr_accessor :cpu
|
15
|
+
attr_accessor :os
|
16
|
+
|
17
|
+
def dump
|
18
|
+
parts = general_prefix
|
19
|
+
parts << %Q{"#{cpu}" "#{os}"}
|
20
|
+
parts.join(' ')
|
21
|
+
end
|
22
|
+
|
23
|
+
def load(string, options = {})
|
24
|
+
rdata = load_general_and_get_rdata(string, options)
|
25
|
+
return nil unless rdata
|
26
|
+
|
27
|
+
captures = rdata.match(REGEX_HINFO_RDATA)
|
28
|
+
return nil unless captures
|
29
|
+
|
30
|
+
@cpu = captures[:cpu].scan(/#{REGEX_QUOTES_OPTIONAL}/).join
|
31
|
+
@os = captures[:os].scan(/"#{DNS::Zone::RR::REGEX_STRING}"|#{DNS::Zone::RR::REGEX_STRING}/).join
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/dns/zone/rr/mx.rb
CHANGED
@@ -3,14 +3,31 @@
|
|
3
3
|
# RFC 1035
|
4
4
|
class DNS::Zone::RR::MX < DNS::Zone::RR::Record
|
5
5
|
|
6
|
-
|
6
|
+
REGEX_MX_RDATA = %r{
|
7
|
+
(?<priority>\d+)\s*
|
8
|
+
(?<exchange>#{DNS::Zone::RR::REGEX_DOMAINNAME})\s*
|
9
|
+
}mx
|
10
|
+
|
11
|
+
attr_accessor :priority
|
7
12
|
attr_accessor :exchange
|
8
13
|
|
9
|
-
def
|
14
|
+
def dump
|
10
15
|
parts = general_prefix
|
11
|
-
parts <<
|
16
|
+
parts << priority
|
12
17
|
parts << exchange
|
13
18
|
parts.join(' ')
|
14
19
|
end
|
15
20
|
|
21
|
+
def load(string, options = {})
|
22
|
+
rdata = load_general_and_get_rdata(string, options)
|
23
|
+
return nil unless rdata
|
24
|
+
|
25
|
+
captures = rdata.match(REGEX_MX_RDATA)
|
26
|
+
return nil unless captures
|
27
|
+
|
28
|
+
@priority = captures[:priority].to_i
|
29
|
+
@exchange = captures[:exchange]
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
16
33
|
end
|
data/lib/dns/zone/rr/ns.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# `PTR` resource record.
|
2
|
+
#
|
3
|
+
# RFC 1035
|
4
|
+
class DNS::Zone::RR::PTR < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
attr_accessor :name
|
7
|
+
|
8
|
+
def dump
|
9
|
+
parts = general_prefix
|
10
|
+
parts << @name
|
11
|
+
parts.join(' ')
|
12
|
+
end
|
13
|
+
|
14
|
+
def load(string, options = {})
|
15
|
+
rdata = load_general_and_get_rdata(string, options)
|
16
|
+
return nil unless rdata
|
17
|
+
@name = rdata
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/dns/zone/rr/record.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Parent class of all RR types, common resource record code lives here.
|
2
2
|
# Is responsible for building a Ruby object given a RR string.
|
3
3
|
#
|
4
|
-
# @abstract Each RR TYPE should subclass and override: {#load} and #{
|
4
|
+
# @abstract Each RR TYPE should subclass and override: {#load} and #{dump}
|
5
5
|
class DNS::Zone::RR::Record
|
6
6
|
|
7
7
|
attr_accessor :label, :ttl
|
@@ -43,7 +43,7 @@ class DNS::Zone::RR::Record
|
|
43
43
|
# Build RR zone file output.
|
44
44
|
#
|
45
45
|
# @return [String] RR zone file output
|
46
|
-
def
|
46
|
+
def dump
|
47
47
|
general_prefix.join(' ')
|
48
48
|
end
|
49
49
|
|
@@ -53,7 +53,7 @@ class DNS::Zone::RR::Record
|
|
53
53
|
# @option options [String] :last_label The last label used by the previous RR
|
54
54
|
# @return [Object]
|
55
55
|
def load(string, options = {})
|
56
|
-
raise
|
56
|
+
raise NotImplementedError, "#load method must be implemented by subclass (#{self.class})"
|
57
57
|
end
|
58
58
|
|
59
59
|
# Load 'general' RR data/params and return the remaining RDATA for further parsing.
|
@@ -65,10 +65,10 @@ class DNS::Zone::RR::Record
|
|
65
65
|
# strip comments, unless its escaped.
|
66
66
|
string.gsub!(/(?<!\\);.*/o, "");
|
67
67
|
|
68
|
-
captures = string.match(DNS::Zone::RR::
|
68
|
+
captures = string.match(DNS::Zone::RR::REGEX_RR)
|
69
69
|
return nil unless captures
|
70
70
|
|
71
|
-
if captures[:label]
|
71
|
+
if [' ', nil].include?(captures[:label])
|
72
72
|
@label = options[:last_label]
|
73
73
|
else
|
74
74
|
@label = captures[:label]
|
data/lib/dns/zone/rr/soa.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
# `SRV` resource record.
|
2
2
|
#
|
3
|
-
# RFC
|
3
|
+
# RFC 1035
|
4
4
|
class DNS::Zone::RR::SOA < DNS::Zone::RR::Record
|
5
5
|
|
6
|
-
|
7
|
-
(?<nameserver>#{DNS::Zone::RR::
|
8
|
-
(?<email>#{DNS::Zone::RR::
|
6
|
+
REGEX_SOA_RDATA = %r{
|
7
|
+
(?<nameserver>#{DNS::Zone::RR::REGEX_DOMAINNAME})\s* # get nameserver domainname
|
8
|
+
(?<email>#{DNS::Zone::RR::REGEX_DOMAINNAME})\s* # get mailbox domainname
|
9
9
|
(?<serial>\d+)\s*
|
10
|
-
(?<refresh_ttl>#{DNS::Zone::RR::
|
11
|
-
(?<retry_ttl>#{DNS::Zone::RR::
|
12
|
-
(?<expiry_ttl>#{DNS::Zone::RR::
|
13
|
-
(?<minimum_ttl>#{DNS::Zone::RR::
|
10
|
+
(?<refresh_ttl>#{DNS::Zone::RR::REGEX_TTL})\s*
|
11
|
+
(?<retry_ttl>#{DNS::Zone::RR::REGEX_TTL})\s*
|
12
|
+
(?<expiry_ttl>#{DNS::Zone::RR::REGEX_TTL})\s*
|
13
|
+
(?<minimum_ttl>#{DNS::Zone::RR::REGEX_TTL})\s*
|
14
14
|
}mx
|
15
15
|
|
16
16
|
attr_accessor :nameserver, :email, :serial, :refresh_ttl, :retry_ttl, :expiry_ttl, :minimum_ttl
|
17
17
|
|
18
|
-
def
|
18
|
+
def dump
|
19
19
|
parts = general_prefix
|
20
20
|
parts << nameserver
|
21
21
|
parts << email
|
@@ -34,7 +34,7 @@ class DNS::Zone::RR::SOA < DNS::Zone::RR::Record
|
|
34
34
|
rdata = load_general_and_get_rdata(string, options)
|
35
35
|
return nil unless rdata
|
36
36
|
|
37
|
-
captures = rdata.match(
|
37
|
+
captures = rdata.match(REGEX_SOA_RDATA)
|
38
38
|
return nil unless captures
|
39
39
|
|
40
40
|
@nameserver = captures[:nameserver]
|
@@ -45,7 +45,6 @@ class DNS::Zone::RR::SOA < DNS::Zone::RR::Record
|
|
45
45
|
@expiry_ttl = captures[:expiry_ttl]
|
46
46
|
@minimum_ttl = captures[:minimum_ttl]
|
47
47
|
|
48
|
-
|
49
48
|
self
|
50
49
|
end
|
51
50
|
|
data/lib/dns/zone/rr/srv.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
# `SRV` resource record.
|
2
2
|
#
|
3
|
-
# RFC
|
3
|
+
# RFC 2782
|
4
4
|
class DNS::Zone::RR::SRV < DNS::Zone::RR::Record
|
5
5
|
|
6
|
+
REGEX_SRV_RDATA = %r{
|
7
|
+
(?<priority>\d+)\s*
|
8
|
+
(?<weight>\d+)\s*
|
9
|
+
(?<port>\d+)\s*
|
10
|
+
(?<target>#{DNS::Zone::RR::REGEX_DOMAINNAME})\s*
|
11
|
+
}mx
|
12
|
+
|
6
13
|
attr_accessor :priority, :weight, :port, :target
|
7
14
|
|
8
|
-
def
|
15
|
+
def dump
|
9
16
|
parts = general_prefix
|
10
17
|
parts << priority
|
11
18
|
parts << weight
|
@@ -14,4 +21,18 @@ class DNS::Zone::RR::SRV < DNS::Zone::RR::Record
|
|
14
21
|
parts.join(' ')
|
15
22
|
end
|
16
23
|
|
24
|
+
def load(string, options = {})
|
25
|
+
rdata = load_general_and_get_rdata(string, options)
|
26
|
+
return nil unless rdata
|
27
|
+
|
28
|
+
captures = rdata.match(REGEX_SRV_RDATA)
|
29
|
+
return nil unless captures
|
30
|
+
|
31
|
+
@priority = captures[:priority].to_i
|
32
|
+
@weight = captures[:weight].to_i
|
33
|
+
@port = captures[:port].to_i
|
34
|
+
@target = captures[:target]
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
17
38
|
end
|
data/lib/dns/zone/rr/txt.rb
CHANGED
@@ -5,7 +5,7 @@ class DNS::Zone::RR::TXT < DNS::Zone::RR::Record
|
|
5
5
|
|
6
6
|
attr_accessor :text
|
7
7
|
|
8
|
-
def
|
8
|
+
def dump
|
9
9
|
parts = general_prefix
|
10
10
|
parts << %Q{"#{text}"}
|
11
11
|
parts.join(' ')
|
@@ -15,7 +15,7 @@ class DNS::Zone::RR::TXT < DNS::Zone::RR::Record
|
|
15
15
|
rdata = load_general_and_get_rdata(string, options)
|
16
16
|
return nil unless rdata
|
17
17
|
# extract text from within quotes; allow multiple quoted strings; ignore escaped quotes
|
18
|
-
@text = rdata.scan(/"
|
18
|
+
@text = rdata.scan(/"#{DNS::Zone::RR::REGEX_STRING}"/).join
|
19
19
|
self
|
20
20
|
end
|
21
21
|
|
data/lib/dns/zone/test_case.rb
CHANGED
data/lib/dns/zone/version.rb
CHANGED
data/test/rr/a_test.rb
CHANGED
@@ -7,20 +7,21 @@ class RR_A_Test < DNS::Zone::TestCase
|
|
7
7
|
|
8
8
|
# ensure we can set address parameter
|
9
9
|
rr.address = '10.0.1.1'
|
10
|
-
assert_equal '
|
10
|
+
assert_equal 'A', rr.type
|
11
|
+
assert_equal '@ IN A 10.0.1.1', rr.dump
|
11
12
|
rr.address = '10.0.2.2'
|
12
|
-
assert_equal '@ IN A 10.0.2.2', rr.
|
13
|
+
assert_equal '@ IN A 10.0.2.2', rr.dump
|
13
14
|
|
14
15
|
# with a label set
|
15
16
|
rr.label = 'labelname'
|
16
|
-
assert_equal 'labelname IN A 10.0.2.2', rr.
|
17
|
+
assert_equal 'labelname IN A 10.0.2.2', rr.dump
|
17
18
|
|
18
19
|
# with a ttl
|
19
20
|
rr.ttl = '4w'
|
20
|
-
assert_equal 'labelname 4w IN A 10.0.2.2', rr.
|
21
|
+
assert_equal 'labelname 4w IN A 10.0.2.2', rr.dump
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
+
def test_load_rr__a
|
24
25
|
rr = DNS::Zone::RR::A.new.load('@ IN A 127.0.0.1')
|
25
26
|
assert_equal '@', rr.label
|
26
27
|
assert_equal 'A', rr.type
|
data/test/rr/aaaa_test.rb
CHANGED
@@ -7,7 +7,21 @@ class RR_AAAA_Test < DNS::Zone::TestCase
|
|
7
7
|
|
8
8
|
# ensure we can set address parameter
|
9
9
|
rr.address = '2001:db8::3'
|
10
|
-
assert_equal '
|
10
|
+
assert_equal 'AAAA', rr.type
|
11
|
+
assert_equal '@ IN AAAA 2001:db8::3', rr.dump
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_load_rr__aaaa
|
15
|
+
rr = DNS::Zone::RR::AAAA.new.load('@ IN AAAA 2001:db8::6')
|
16
|
+
assert_equal '@', rr.label
|
17
|
+
assert_equal 'AAAA', rr.type
|
18
|
+
assert_equal '2001:db8::6', rr.address
|
19
|
+
|
20
|
+
rr = DNS::Zone::RR::AAAA.new.load('www IN A 2001:db8::6')
|
21
|
+
assert_equal 'www', rr.label
|
22
|
+
assert_equal 'AAAA', rr.type
|
23
|
+
assert_equal 'IN', rr.klass
|
24
|
+
assert_equal '2001:db8::6', rr.address
|
11
25
|
end
|
12
26
|
|
13
27
|
end
|
data/test/rr/cname_test.rb
CHANGED
@@ -6,7 +6,14 @@ class RR_CNAME_Test < DNS::Zone::TestCase
|
|
6
6
|
rr = DNS::Zone::RR::CNAME.new
|
7
7
|
rr.label = 'google9d97d7f266ee521d'
|
8
8
|
rr.domainname = 'google.com.'
|
9
|
-
assert_equal 'google9d97d7f266ee521d IN CNAME google.com.', rr.
|
9
|
+
assert_equal 'google9d97d7f266ee521d IN CNAME google.com.', rr.dump
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_load_rr__cname
|
13
|
+
rr = DNS::Zone::RR::CNAME.new.load('foo IN CNAME example.com.')
|
14
|
+
assert_equal 'foo', rr.label
|
15
|
+
assert_equal 'CNAME', rr.type
|
16
|
+
assert_equal 'example.com.', rr.domainname
|
10
17
|
end
|
11
18
|
|
12
19
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'dns/zone/test_case'
|
2
|
+
|
3
|
+
class RR_HINFO_Test < DNS::Zone::TestCase
|
4
|
+
|
5
|
+
def test_build_rr__hinfo
|
6
|
+
rr = DNS::Zone::RR::HINFO.new
|
7
|
+
rr.cpu = 'Intel'
|
8
|
+
rr.os = 'Ubuntu'
|
9
|
+
assert_equal '@ IN HINFO "Intel" "Ubuntu"', rr.dump
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_build_with_spaces
|
13
|
+
rr = DNS::Zone::RR::HINFO.new
|
14
|
+
rr.label = 'ns0'
|
15
|
+
rr.cpu = 'PC Intel 700mhz'
|
16
|
+
rr.os = 'Ubuntu 12.04 LTS'
|
17
|
+
assert_equal 'ns0 IN HINFO "PC Intel 700mhz" "Ubuntu 12.04 LTS"', rr.dump
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_load_rr__hinfo
|
21
|
+
rr = DNS::Zone::RR::HINFO.new.load('ns0 IN HINFO "Intel" "Ubuntu"')
|
22
|
+
assert_equal 'ns0', rr.label
|
23
|
+
assert_equal 'HINFO', rr.type
|
24
|
+
assert_equal 'Intel', rr.cpu
|
25
|
+
assert_equal 'Ubuntu', rr.os
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_load_with_spaces
|
29
|
+
rr = DNS::Zone::RR::HINFO.new.load('ns0 IN HINFO "PC Intel 700mhz" "Ubuntu 12.04 LTS"')
|
30
|
+
assert_equal 'PC Intel 700mhz', rr.cpu
|
31
|
+
assert_equal 'Ubuntu 12.04 LTS', rr.os
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_load_mixed_quotes
|
35
|
+
rr = DNS::Zone::RR::HINFO.new.load('ns0 IN HINFO Intel "Ubuntu 12.04"')
|
36
|
+
assert_equal 'Intel', rr.cpu
|
37
|
+
assert_equal 'Ubuntu 12.04', rr.os
|
38
|
+
|
39
|
+
rr = DNS::Zone::RR::HINFO.new.load('ns0 IN HINFO "PC Intel" Ubuntu')
|
40
|
+
assert_equal 'PC Intel', rr.cpu
|
41
|
+
assert_equal 'Ubuntu', rr.os
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/test/rr/mx_test.rb
CHANGED
@@ -5,14 +5,22 @@ class RR_MX_Test < DNS::Zone::TestCase
|
|
5
5
|
def test_build_rr__mx
|
6
6
|
rr = DNS::Zone::RR::MX.new
|
7
7
|
|
8
|
-
# ensure we can set
|
9
|
-
rr.
|
8
|
+
# ensure we can set priority and exchange parameter
|
9
|
+
rr.priority = 10
|
10
10
|
rr.exchange = 'mx0.lividpenguin.com.'
|
11
|
-
assert_equal '@ IN MX 10 mx0.lividpenguin.com.', rr.
|
11
|
+
assert_equal '@ IN MX 10 mx0.lividpenguin.com.', rr.dump
|
12
12
|
|
13
|
-
rr.
|
13
|
+
rr.priority = 20
|
14
14
|
rr.exchange = 'mx1.lividpenguin.com.'
|
15
|
-
assert_equal '@ IN MX 20 mx1.lividpenguin.com.', rr.
|
15
|
+
assert_equal '@ IN MX 20 mx1.lividpenguin.com.', rr.dump
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_load_rr__mx
|
19
|
+
rr = DNS::Zone::RR::MX.new.load('@ IN MX 20 mx1.lividpenguin.com.')
|
20
|
+
assert_equal '@', rr.label
|
21
|
+
assert_equal 'MX', rr.type
|
22
|
+
assert_equal 20, rr.priority
|
23
|
+
assert_equal 'mx1.lividpenguin.com.', rr.exchange
|
16
24
|
end
|
17
25
|
|
18
26
|
end
|
data/test/rr/ns_test.rb
CHANGED
@@ -5,7 +5,14 @@ class RR_NS_Test < DNS::Zone::TestCase
|
|
5
5
|
def test_build_rr__ns
|
6
6
|
rr = DNS::Zone::RR::NS.new
|
7
7
|
rr.nameserver = 'ns0.lividpenguin.com.'
|
8
|
-
assert_equal '@ IN NS ns0.lividpenguin.com.', rr.
|
8
|
+
assert_equal '@ IN NS ns0.lividpenguin.com.', rr.dump
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_load_rr__ns
|
12
|
+
rr = DNS::Zone::RR::NS.new.load('@ IN NS ns0.lividpenguin.com.')
|
13
|
+
assert_equal '@', rr.label
|
14
|
+
assert_equal 'NS', rr.type
|
15
|
+
assert_equal 'ns0.lividpenguin.com.', rr.nameserver
|
9
16
|
end
|
10
17
|
|
11
18
|
end
|
data/test/rr/ptr_test.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'dns/zone/test_case'
|
2
|
+
|
3
|
+
class RR_PTR_Test < DNS::Zone::TestCase
|
4
|
+
|
5
|
+
def test_build_rr__ptr
|
6
|
+
rr = DNS::Zone::RR::PTR.new
|
7
|
+
rr.label = '69'
|
8
|
+
rr.name = 'mx0.lividpenguin.com.'
|
9
|
+
assert_equal '69 IN PTR mx0.lividpenguin.com.', rr.dump
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_load_rr__ptr
|
13
|
+
rr = DNS::Zone::RR::PTR.new.load('69 IN PTR mx0.lividpenguin.com.')
|
14
|
+
assert_equal '69', rr.label
|
15
|
+
assert_equal 'PTR', rr.type
|
16
|
+
assert_equal 'mx0.lividpenguin.com.', rr.name
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/test/rr/record_test.rb
CHANGED
@@ -11,20 +11,27 @@ class RR_Record_Test < DNS::Zone::TestCase
|
|
11
11
|
def test_rr_record_with_label
|
12
12
|
rr = DNS::Zone::RR::Record.new
|
13
13
|
rr.label = 'labelname'
|
14
|
-
assert_equal 'labelname IN <type>', rr.
|
14
|
+
assert_equal 'labelname IN <type>', rr.dump
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_rr_record_with_label_and_ttl
|
18
18
|
rr = DNS::Zone::RR::Record.new
|
19
19
|
rr.label = 'labelname'
|
20
20
|
rr.ttl = '2d'
|
21
|
-
assert_equal 'labelname 2d IN <type>', rr.
|
21
|
+
assert_equal 'labelname 2d IN <type>', rr.dump
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_rr_record_with_ttl
|
25
25
|
rr = DNS::Zone::RR::Record.new
|
26
26
|
rr.ttl = '2d'
|
27
|
-
assert_equal '@ 2d IN <type>', rr.
|
27
|
+
assert_equal '@ 2d IN <type>', rr.dump
|
28
|
+
end
|
29
|
+
|
30
|
+
# the load method should be overloaded by a subclass, calling direct should raise
|
31
|
+
def test_record_load_default_method_raises_exception
|
32
|
+
assert_raises(NotImplementedError) {
|
33
|
+
DNS::Zone::RR::Record.new.load('')
|
34
|
+
}
|
28
35
|
end
|
29
36
|
|
30
37
|
end
|
data/test/rr/soa_test.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'dns/zone/test_case'
|
2
2
|
|
3
|
-
class
|
3
|
+
class RR_SOA_Test < DNS::Zone::TestCase
|
4
4
|
|
5
5
|
EXAMPLE_SOA_IN = '@ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. 2014021601 3h 15m 4w 30m'
|
6
6
|
EXAMPLE_SOA_OUT = '@ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. ( 2014021601 3h 15m 4w 30m )'
|
7
7
|
|
8
|
-
def
|
8
|
+
def test_build_rr__soa
|
9
9
|
rr = DNS::Zone::RR::SOA.new
|
10
10
|
rr.nameserver = 'ns0.lividpenguin.com.'
|
11
11
|
rr.email = 'luke.lividpenguin.com.'
|
@@ -14,10 +14,10 @@ class RR_SRV_Test < DNS::Zone::TestCase
|
|
14
14
|
rr.retry_ttl = '15m'
|
15
15
|
rr.expiry_ttl = '4w'
|
16
16
|
rr.minimum_ttl = '30m'
|
17
|
-
assert_equal EXAMPLE_SOA_OUT, rr.
|
17
|
+
assert_equal EXAMPLE_SOA_OUT, rr.dump
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def test_load_rr__soa
|
21
21
|
rr = DNS::Zone::RR::SOA.new.load(EXAMPLE_SOA_IN)
|
22
22
|
assert_equal '@', rr.label
|
23
23
|
assert_equal 'SOA', rr.type
|
data/test/rr/spf_test.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'dns/zone/test_case'
|
2
|
+
|
3
|
+
class RR_SPF_Test < DNS::Zone::TestCase
|
4
|
+
|
5
|
+
def test_build_rr__spf
|
6
|
+
rr = DNS::Zone::RR::SPF.new
|
7
|
+
rr.ttl = '2w'
|
8
|
+
rr.text = 'v=spf1 +mx -all'
|
9
|
+
assert_equal '@ 2w IN SPF "v=spf1 +mx -all"', rr.dump
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_load_rr__spf
|
13
|
+
rr = DNS::Zone::RR::SPF.new.load('@ 2w IN SPF "v=spf1 +mx -all"')
|
14
|
+
assert_equal '@', rr.label
|
15
|
+
assert_equal 'IN', rr.klass
|
16
|
+
assert_equal 'SPF', rr.type
|
17
|
+
assert_equal 'v=spf1 +mx -all', rr.text
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/test/rr/srv_test.rb
CHANGED
@@ -8,7 +8,17 @@ class RR_SRV_Test < DNS::Zone::TestCase
|
|
8
8
|
rr.weight = 0
|
9
9
|
rr.port = 5269
|
10
10
|
rr.target = 'xmpp-server.l.google.com.'
|
11
|
-
assert_equal '@ IN SRV 5 0 5269 xmpp-server.l.google.com.', rr.
|
11
|
+
assert_equal '@ IN SRV 5 0 5269 xmpp-server.l.google.com.', rr.dump
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_load_rr__srv
|
15
|
+
rr = DNS::Zone::RR::SRV.new.load('@ IN SRV 5 0 5269 xmpp-server.l.google.com.')
|
16
|
+
assert_equal '@', rr.label
|
17
|
+
assert_equal 'SRV', rr.type
|
18
|
+
assert_equal 5, rr.priority
|
19
|
+
assert_equal 0, rr.weight
|
20
|
+
assert_equal 5269, rr.port
|
21
|
+
assert_equal 'xmpp-server.l.google.com.', rr.target
|
12
22
|
end
|
13
23
|
|
14
24
|
end
|
data/test/rr/txt_test.rb
CHANGED
@@ -7,18 +7,18 @@ class RR_TXT_Test < DNS::Zone::TestCase
|
|
7
7
|
|
8
8
|
# ensure we can set text parameter
|
9
9
|
rr.text = 'test text'
|
10
|
-
assert_equal '@ IN TXT "test text"', rr.
|
10
|
+
assert_equal '@ IN TXT "test text"', rr.dump
|
11
11
|
|
12
12
|
# with a label set
|
13
13
|
rr.label = 'labelname'
|
14
|
-
assert_equal 'labelname IN TXT "test text"', rr.
|
14
|
+
assert_equal 'labelname IN TXT "test text"', rr.dump
|
15
15
|
|
16
16
|
# with a ttl
|
17
17
|
rr.ttl = '2w'
|
18
|
-
assert_equal 'labelname 2w IN TXT "test text"', rr.
|
18
|
+
assert_equal 'labelname 2w IN TXT "test text"', rr.dump
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def test_load_rr__txt
|
22
22
|
rr = DNS::Zone::RR::TXT.new.load('txtrecord IN TXT "test text"')
|
23
23
|
assert_equal 'txtrecord', rr.label
|
24
24
|
assert_equal 'IN', rr.klass
|
data/test/zone_test.rb
CHANGED
@@ -2,46 +2,118 @@ require 'dns/zone/test_case'
|
|
2
2
|
|
3
3
|
class ZoneTest < DNS::Zone::TestCase
|
4
4
|
|
5
|
-
|
5
|
+
# example zone file, with a couple of things that could trip us up.
|
6
|
+
ZONE_FILE_EXAMPLE =<<-EOL
|
6
7
|
$ORIGIN lividpenguin.com.
|
7
8
|
$TTL 3d
|
8
|
-
@
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
; a more difficult ; comment (
|
17
|
-
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
21
|
-
|
22
|
-
@
|
23
|
-
@
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
9
|
+
@ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. (
|
10
|
+
2013101406 ; zone serial number
|
11
|
+
12h ; refresh ttl
|
12
|
+
15m ; retry ttl
|
13
|
+
3w ; expiry ttl
|
14
|
+
3h ; minimum ttl
|
15
|
+
)
|
16
|
+
|
17
|
+
; a more difficult ; comment ( that is trying to break things!
|
18
|
+
|
19
|
+
@ IN NS ns0.lividpenguin.com.
|
20
|
+
@ IN NS ns1.lividpenguin.com.
|
21
|
+
@ IN NS ns2.lividpenguin.com.
|
22
|
+
|
23
|
+
@ IN MX 10 mx0.lividpenguin.com.
|
24
|
+
@ IN MX 20 mx1.lividpenguin.com.
|
25
|
+
|
26
|
+
@ IN A 78.47.253.85
|
27
|
+
ns0 IN A 78.47.253.85
|
28
|
+
ns0 IN HINFO "Intel" "Ubuntu"
|
29
|
+
|
30
|
+
ns0 IN AAAA 2a01:4f8:d12:5ca::2
|
31
|
+
|
32
|
+
foo IN TXT "part1""part2"
|
33
|
+
bar IN TXT ("part1 "
|
34
|
+
"part2 "
|
35
|
+
"part3")
|
36
|
+
|
37
|
+
longttl 5d IN A 10.1.2.3
|
38
|
+
|
39
|
+
cake IN CNAME the.cake.is.a.lie.com.
|
40
|
+
xmpp IN SRV 5 0 5269 xmpp-server.google.com.
|
41
|
+
@ IN SPF "v=spf1 +mx -all"
|
42
|
+
|
43
|
+
; a record to be expanded
|
44
|
+
@ IN NS ns3
|
45
|
+
|
46
|
+
; a record that uses tab spaces
|
47
|
+
tabed IN A 10.1.2.3
|
48
|
+
|
49
|
+
EOL
|
50
|
+
|
51
|
+
# basic zone file example
|
52
|
+
ZONE_FILE_BASIC_EXAMPLE =<<-EOL
|
53
|
+
@ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. ( 2013101406 12h 15m 3w 3h )
|
54
|
+
@ IN NS ns0.lividpenguin.com.
|
55
|
+
@ IN A 78.47.253.85
|
29
56
|
EOL
|
30
57
|
|
31
58
|
def test_create_new_instance
|
32
59
|
assert DNS::Zone.new
|
33
60
|
end
|
34
61
|
|
35
|
-
def
|
36
|
-
zone
|
62
|
+
def test_load_zone_basic
|
63
|
+
# load zone file.
|
64
|
+
zone = DNS::Zone.load(ZONE_FILE_BASIC_EXAMPLE)
|
65
|
+
# dump zone file.
|
66
|
+
dump = zone.dump
|
67
|
+
# check input matches output.
|
68
|
+
assert_equal ZONE_FILE_BASIC_EXAMPLE, dump, 'loaded zone file should match dumped zone file'
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_load_zone
|
72
|
+
# load example dns master zone file.
|
73
|
+
zone = DNS::Zone.load(ZONE_FILE_EXAMPLE)
|
74
|
+
|
75
|
+
# test attributes are correct.
|
37
76
|
assert_equal '3d', zone.ttl, 'check ttl matches example input'
|
38
77
|
assert_equal 'lividpenguin.com.', zone.origin, 'check origin matches example input'
|
39
|
-
assert_equal
|
78
|
+
assert_equal 18, zone.records.length, 'we should have multiple records (including SOA)'
|
79
|
+
|
80
|
+
#p ''
|
81
|
+
#zone.records.each do |rec|
|
82
|
+
# p rec
|
83
|
+
#end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_load_zone_with_empty_labels
|
87
|
+
# basic zone file that uses empty labels (ie. use previous)
|
88
|
+
zone_as_string =<<-EOL
|
89
|
+
@ IN A 78.47.253.85
|
90
|
+
IN AAAA 2a01:4f8:d12:5ca::2
|
91
|
+
www IN A 78.47.253.85
|
92
|
+
IN AAAA 2a01:4f8:d12:5ca::2
|
93
|
+
EOL
|
94
|
+
|
95
|
+
# load zone file.
|
96
|
+
zone = DNS::Zone.load(zone_as_string)
|
40
97
|
|
41
|
-
|
42
|
-
zone.records.
|
43
|
-
|
44
|
-
|
98
|
+
# test labels are 'inherited' from last used.
|
99
|
+
assert_equal '@', zone.records[0].label
|
100
|
+
assert_equal '@', zone.records[1].label, 'label should be inherited from last label used'
|
101
|
+
assert_equal 'www', zone.records[2].label
|
102
|
+
assert_equal 'www', zone.records[3].label, 'label should be inherited from last label used'
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_load_zone_that_uses_tabs_rather_then_spaces
|
106
|
+
zone_as_string =<<-EOL
|
107
|
+
* IN A 78.47.253.85
|
108
|
+
EOL
|
109
|
+
|
110
|
+
# load zone file.
|
111
|
+
zone = DNS::Zone.load(zone_as_string)
|
112
|
+
|
113
|
+
record = zone.records[0]
|
114
|
+
assert_equal '*', record.label
|
115
|
+
assert_equal 'A', record.type
|
116
|
+
assert_equal '78.47.253.85', record.address
|
45
117
|
end
|
46
118
|
|
47
119
|
def test_extract_entry_from_one_line
|
@@ -107,5 +179,4 @@ EOL
|
|
107
179
|
assert_equal 'maiow IN TXT "purr((maiow)"', entries[0], 'entry should match expected'
|
108
180
|
end
|
109
181
|
|
110
|
-
|
111
182
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dns-zone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Antins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,98 +16,98 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '1.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '9.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '9.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '5.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '5.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: simplecov
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 0.7.1
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 0.7.1
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
75
|
+
version: '0.8'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
82
|
+
version: '0.8'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: inch
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
89
|
+
version: '0.3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
96
|
+
version: '0.3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: guard-minitest
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
103
|
+
version: '2.0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
110
|
+
version: '2.0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: guard-bundler
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,10 +142,13 @@ files:
|
|
142
142
|
- lib/dns/zone/rr/a.rb
|
143
143
|
- lib/dns/zone/rr/aaaa.rb
|
144
144
|
- lib/dns/zone/rr/cname.rb
|
145
|
+
- lib/dns/zone/rr/hinfo.rb
|
145
146
|
- lib/dns/zone/rr/mx.rb
|
146
147
|
- lib/dns/zone/rr/ns.rb
|
148
|
+
- lib/dns/zone/rr/ptr.rb
|
147
149
|
- lib/dns/zone/rr/record.rb
|
148
150
|
- lib/dns/zone/rr/soa.rb
|
151
|
+
- lib/dns/zone/rr/spf.rb
|
149
152
|
- lib/dns/zone/rr/srv.rb
|
150
153
|
- lib/dns/zone/rr/txt.rb
|
151
154
|
- lib/dns/zone/test_case.rb
|
@@ -153,10 +156,13 @@ files:
|
|
153
156
|
- test/rr/a_test.rb
|
154
157
|
- test/rr/aaaa_test.rb
|
155
158
|
- test/rr/cname_test.rb
|
159
|
+
- test/rr/hinfo_test.rb
|
156
160
|
- test/rr/mx_test.rb
|
157
161
|
- test/rr/ns_test.rb
|
162
|
+
- test/rr/ptr_test.rb
|
158
163
|
- test/rr/record_test.rb
|
159
164
|
- test/rr/soa_test.rb
|
165
|
+
- test/rr/spf_test.rb
|
160
166
|
- test/rr/srv_test.rb
|
161
167
|
- test/rr/txt_test.rb
|
162
168
|
- test/rr_test.rb
|
@@ -177,9 +183,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
177
183
|
version: '1.9'
|
178
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
185
|
requirements:
|
180
|
-
- - "
|
186
|
+
- - ">="
|
181
187
|
- !ruby/object:Gem::Version
|
182
|
-
version:
|
188
|
+
version: '0'
|
183
189
|
requirements: []
|
184
190
|
rubyforge_project:
|
185
191
|
rubygems_version: 2.2.0
|