Class: DNS::Zone
- Inherits:
-
Object
- Object
- DNS::Zone
- Defined in:
- lib/dns/zone.rb,
lib/dns/zone/rr.rb,
lib/dns/zone/version.rb
Overview
Represents a ‘whole’ zone of many resource records (RRs).
This is also the primary namespace for the ‘dns-zone` gem.
Defined Under Namespace
Constant Summary collapse
- Version =
Version number (major.minor.tiny)
'0.3.2'
Instance Attribute Summary collapse
-
#origin ⇒ Object
The primary $ORIGIN (directive) of the zone.
-
#records ⇒ Object
Array of all the zones RRs (including the SOA).
-
#ttl ⇒ Object
The default $TTL (directive) of the zone.
Class Method Summary collapse
-
.extract_entries(string) ⇒ Object
private
Extract entries from a zone file that will be later parsed as RRs.
-
.load(string, default_origin = "") ⇒ Object
Load the provided zone file data into a new DNS::Zone object.
Instance Method Summary collapse
-
#dump ⇒ Object
Generates output of the zone and its records.
-
#dump_pretty ⇒ Object
Generates pretty output of the zone and its records.
-
#initialize ⇒ Zone
constructor
Create an empty instance of a DNS zone that you can drive programmatically.
-
#soa ⇒ Object
Helper method to access the zones SOA RR.
Constructor Details
#initialize ⇒ Zone
Create an empty instance of a DNS zone that you can drive programmatically.
22 23 24 25 26 27 28 29 30 31 |
# File 'lib/dns/zone.rb', line 22 def initialize @records = [] soa = DNS::Zone::RR::SOA.new # set a couple of defaults on the SOA soa.serial = Time.now.utc.strftime("%Y%m%d01") soa.refresh_ttl = '3h' soa.retry_ttl = '15m' soa.expiry_ttl = '4w' soa.minimum_ttl = '30m' end |
Instance Attribute Details
#origin ⇒ Object
The primary $ORIGIN (directive) of the zone.
15 16 17 |
# File 'lib/dns/zone.rb', line 15 def origin @origin end |
#records ⇒ Object
Array of all the zones RRs (including the SOA).
17 18 19 |
# File 'lib/dns/zone.rb', line 17 def records @records end |
#ttl ⇒ Object
The default $TTL (directive) of the zone.
13 14 15 |
# File 'lib/dns/zone.rb', line 13 def ttl @ttl end |
Class Method Details
.extract_entries(string) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Extract entries from a zone file that will be later parsed as RRs.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/dns/zone.rb', line 123 def self.extract_entries(string) # FROM RFC: # The format of these files is a sequence of entries. Entries are # predominantly line-oriented, though parentheses can be used to continue # a list of items across a line boundary, and text literals can contain # CRLF within the text. Any combination of tabs and spaces act as a # delimiter between the separate items that make up an entry. The end of # any line in the master file can end with a comment. The comment starts # with a ";" (semicolon). entries = [] mode = :line entry = '' parentheses_ref_count = 0 string.lines.each do |line| # strip comments unless escaped # strip comments, unless its escaped. # skip semicolons within "quote segments" (TXT records) line = line.gsub(/((?<!\\);)(?=(?:[^"]|"[^"]*")*$).*/o, "").chomp next if line.gsub(/\s+/, '').empty? # append to entry line entry << line quotes = entry.count('"') has_quotes = quotes > 0 parentheses = entry.count('()') has_parentheses = parentheses > 0 if has_quotes character_strings = entry.scan(/("(?:[^"\\]+|\\.)*")/).join(' ') without = entry.gsub(/"((?:[^"\\]+|\\.)*)"/, '') parentheses_ref_count = without.count('(') - without.count(')') else parentheses_ref_count = entry.count('(') - entry.count(')') end # are parentheses balanced? if parentheses_ref_count == 0 if has_quotes without.gsub!(/[()]/, '') without.gsub!(/[ ]{2,}/, ' ') #entries << (without + character_strings) entry = (without + character_strings) else entry.gsub!(/[()]/, '') entry.gsub!(/[ ]{2,}/, ' ') entry.gsub!(/[ ]+$/, '') #entries << entry end entries << entry entry = '' end end return entries end |
.load(string, default_origin = "") ⇒ Object
Load the provided zone file data into a new DNS::Zone object.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/dns/zone.rb', line 84 def self.load(string, default_origin = "") # get entries entries = self.extract_entries(string) instance = self.new = {} entries.each do |entry| # read in special statments like $TTL and $ORIGIN if entry =~ /\$(ORIGIN|TTL)\s+(.+)/ instance.ttl = $2 if $1 == 'TTL' if $1 == 'ORIGIN' instance.origin ||= $2 [:origin] ||= $2 [:last_origin] = $2 end next end # parse each RR and create a Ruby object for it if entry =~ DNS::Zone::RR::REGEX_RR rec = DNS::Zone::RR.load(entry, ) next unless rec instance.records << rec [:last_label] = rec.label end end # use default_origin if we didn't see a ORIGIN directive in the zone if instance.origin.to_s.empty? && !default_origin.empty? instance.origin = default_origin end return instance end |
Instance Method Details
#dump ⇒ Object
Generates output of the zone and its records.
55 56 57 58 59 60 61 62 63 |
# File 'lib/dns/zone.rb', line 55 def dump content = [] @records.each do |rr| content << rr.dump end content.join("\n") << "\n" end |
#dump_pretty ⇒ Object
Generates pretty output of the zone and its records.
68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/dns/zone.rb', line 68 def dump_pretty content = [] last_type = "SOA" sorted_records.each do |rr| content << '' if last_type != rr.type content << rr.dump last_type = rr.type end content.join("\n") << "\n" end |
#soa ⇒ Object
Helper method to access the zones SOA RR.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/dns/zone.rb', line 36 def soa # return the first SOA we find in the records array. rr = @records.find { |rr| rr.type == "SOA" } return rr if rr # otherwise create a new SOA rr = DNS::Zone::RR::SOA.new rr.serial = Time.now.utc.strftime("%Y%m%d01") rr.refresh_ttl = '3h' rr.retry_ttl = '15m' rr.expiry_ttl = '4w' rr.minimum_ttl = '30m' # store and return new SOA @records << rr return rr end |