redzone 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZGIzOTRjZmY0MmE1YmNmYTA0YjFlODAxYzY5NzgxNDg0YmI5ODc3MA==
4
+ ZmI1Mjc3YWJmMjYzYTg5YTFhZDlkOGZiMzhhZTUwODFhZDdiNTJjMQ==
5
5
  data.tar.gz: !binary |-
6
- YWY5OGI0YzMyOWNjMGNjOWY4ZThkOGJkMmJjMzBmNzYzYzRjNWQyMQ==
6
+ ODU2Mjk3NDc2YWM5MGFiNjExOTg1Nzc4Mzg1OWIxMWNlZGI1M2ZkYw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NTI0Y2ZhZjhmMTg3Y2VkODc3MDBhMDY0N2VlZmRjODhiMWJkODgxOTU3MmZk
10
- NzBkZTYwNzk0ODVlYzBlNzYxNGViN2EzZjQwOTlhZTI2NTgzNmY2MzczM2My
11
- ZDg4NjFmYTM5NzE0YmQ4MDRiZjI5NzdjOWM1ZWM4N2E1YTgwNWE=
9
+ YTRhNzRmYjZkYzZhYWRiNjI2MWYzZDMwNWM0OGIzYTRlOTE1ZjYwMDU4YWNm
10
+ ZWMyNWFhMTdhZDBjODcwOWVlNDU3YWI5ODRhNGEwYjc0ODA5M2QyNmIxYWRh
11
+ NGNiOTNmNTk3MzE1YTg3ZWQ0N2Q2NTFlYjUwODQ3ZGQ1ZDhlMjg=
12
12
  data.tar.gz: !binary |-
13
- MTYzMTc3YjRkNjA2OTA3YjVhY2Q4ZDRjOTk2ZDkyYzJmZGFhNzY2ZTkzY2Qx
14
- NTVjMzk5NTU5ODAxODQ1N2Y3ZjVmZTg0N2VlMGI5OWI2MmUzODM3NmVlNzcy
15
- MDQzOGY4MTAzZDRmZTE0YmU1NGNlODYzNjlmYTViOTE2ZTYxZDk=
13
+ ZTk0ODhkOTJkMTFlYTUwNGNjMzA4N2IyYzQ1ZmFlMGFlZTdmY2JiZWE0NTY3
14
+ NGQ1Mjc3MzUyMjdiOWQ4ZDQ2NzEzNzEyNDc5YzdjZWNmZDRiMjE4ODgzMmY2
15
+ NDFhM2M4ZThlOTQ4MjY4ODVlMjYyYmNlNTJkMzBkODk5MDgzYmE=
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+ script: "SPEC_OPTS='--format=d' rake spec"
4
+ rvm:
5
+ - 1.8.7
6
+ - 1.9.3
7
+ - 2.0.0
8
+ - ruby-head
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: ruby-head
12
+ before_install:
13
+ - gem update --system 2.1.11 # todo: workaround for https://github.com/rubygems/rubygems/pull/763
14
+ notifications:
15
+ email: false
data/LICENSE.md CHANGED
@@ -1,6 +1,3 @@
1
- # @markup markdown
2
- # @title MIT License
3
-
4
1
  Copyright (C) 2014 Justen Walker
5
2
 
6
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
data/README.md CHANGED
@@ -1,12 +1,17 @@
1
- # RedZone - Generate BIND zone files from simple YAML syntax
1
+ RedZone
2
+ =======
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/redzone.png)](http://badge.fury.io/rb/redzone)
5
+ [![Build Status](https://travis-ci.org/justenwalker/redzone.png?branch=master)](https://travis-ci.org/justenwalker/redzone)
6
+
7
+ Generate BIND zone files from simple yaml configuration.
2
8
 
3
9
  Introduction
4
10
  ------------
5
11
 
6
- RedZone is a command-line utility for generating BIND DNS zone files from a YAML file. The tools follows the
7
- UNIX philosophy and therefore does not attempt to do anything besides this.
12
+ RedZone is a command-line utility for generating BIND DNS zone files from a YAML file.
8
13
 
9
- RedZone was inspired by Daniel P. Berrange's [NoZone](http://search.cpan.org/~danberr/NoZone-1.0/lib/NoZone.pm) i
14
+ RedZone was inspired by Daniel P. Berrange's [NoZone](http://search.cpan.org/~danberr/NoZone-1.0/lib/NoZone.pm)
10
15
  script which does something very similar in Perl.
11
16
  The notable differences are:
12
17
  - Added support for reverse-dns generation
@@ -17,19 +22,22 @@ The notable differences are:
17
22
  Disclaimer
18
23
  ----------
19
24
 
20
- This gem was just released (pre 1.0) and probably doesn't have everything (or anything) you want yet.
25
+ This gem was just released (pre 1.0) and is not ready for production use yet.
21
26
 
22
27
  During pre 1.0, things may change that break backwards compatibility between releases. Most likely these breaking
23
28
  changes would be related to the YAML file syntax.
24
29
 
25
- ### Current TODO List
26
-
27
- - More test coverage for existing features
30
+ To Do
31
+ -----
32
+ See the [Issue Tracker](https://github.com/justenwalker/redzone/issues)
28
33
 
29
34
  Installation
30
35
  ------------
31
36
 
32
- TODO: Publish to RubyGems.org
37
+ ```
38
+ $ gem install redzone
39
+ ```
40
+ ### gem install redzone
33
41
 
34
42
  Usage
35
43
  -----
@@ -47,17 +55,21 @@ Options:
47
55
  ### Generating zone databases
48
56
 
49
57
  - Create a zones.yml file (See [zones.yml.example]) in `/etc/redzone`
50
- - Execute `redzone generate /var/named`
51
- - Each zone and reverse record database should be present in /var/named
58
+ - Execute `redzone generate /var/named/data`
59
+ - Each zone and reverse record database should be present in `/var/named`
52
60
 
53
61
  For example, if your zone.yml file is like the zones.yml.example file
54
62
  then the resulting db files are:
55
- - `0.0.0.0.0.0.0.0.0.0.c.f.ip6.arpa.db`
56
- - `1.168.192.in-addr.arpa.db`
57
- - `32.12.in-addr.arpa.db`
58
- - `9.8.7.6.4.3.2.1.1.0.0.2.ip6.arpa.db`
59
- - `qa.redzone.com.db`
60
- - `redzone.com.db`
63
+
64
+ ```
65
+ $ ls -1 /var/named/data
66
+ 0.0.0.0.0.0.0.0.0.0.c.f.ip6.arpa.db
67
+ 1.168.192.in-addr.arpa.db
68
+ 32.12.in-addr.arpa.db
69
+ 9.8.7.6.4.3.2.1.1.0.0.2.ip6.arpa.db
70
+ qa.redzone.com.db
71
+ redzone.com.db
72
+ ```
61
73
 
62
74
  How to Contribute
63
75
  -----------------
@@ -79,6 +91,6 @@ Please include a reproducible test case.
79
91
  License
80
92
  -------
81
93
 
82
- Copyright (c) 2013 Justen Walker.
94
+ Copyright (c) 2014 Justen Walker.
83
95
 
84
- Released under the terms of the MIT License. For further information, please see the file [LICENSE.md].
96
+ Released under the terms of the MIT License. For further information, please see the file `LICENSE.md`.
data/Rakefile CHANGED
@@ -1,7 +1,10 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
- require "yard"
4
3
 
4
+ # Optionally require yard and
5
+ # construct document tasks
6
+ begin
7
+ require "yard"
5
8
  yard_files = ['lib/**/*.rb','-','LICENSE.md']
6
9
  yard_opts = [
7
10
  '--markup', 'markdown',
@@ -10,23 +13,25 @@ yard_opts = [
10
13
  '--no-private',
11
14
  '--exclude', 'lib/*/cli.rb'
12
15
  ]
13
-
14
16
  YARD::Rake::YardocTask.new do |t|
15
17
  t.files = yard_files
16
18
  t.options = yard_opts
17
19
  end
18
20
  task :yard_server => [:yard] do
19
- system "yard server --reload"
21
+ system 'yard server --reload'
20
22
  end
23
+ rescue LoadError
24
+ end
25
+
21
26
  begin
22
27
  require 'ci/reporter/rake/rspec'
23
28
  rescue LoadError
24
29
  end
25
30
 
26
31
  RSpec::Core::RakeTask.new(:spec) do |t|
27
- t.pattern = "spec/unit/**/*_spec.rb"
32
+ t.pattern = 'spec/unit/**/*_spec.rb'
28
33
  end
29
34
 
30
35
  task :default do
31
36
  sh %{rake -T}
32
- end
37
+ end
data/lib/redzone/soa.rb CHANGED
@@ -17,6 +17,10 @@ module RedZone
17
17
  #
18
18
  class SOA
19
19
  # Returns a new instance of a zone SOA record
20
+ #
21
+ # See [SOA reference](http://www.zytrax.com/books/dns/ch8/soa.html)
22
+ # for explaination of the fields.
23
+ #
20
24
  # @param [Hash] opts
21
25
  # @option opts [String] :domain Zone (domain) name
22
26
  # @option opts [String] :ns Primary name server
@@ -24,15 +28,17 @@ module RedZone
24
28
  # @option opts [String] :refresh Time between refreshes from slave servers
25
29
  # @option opts [String] :retry Time between retrying failed zone transfers
26
30
  # @option opts [String] :expire The maximum time that a secondary server will keep trying to complete a zone transfer.
31
+ # @option opts [String] :negative The maximum negative caching time.
27
32
  # @option opts [String] :ttl The minimum time-to-live that applies to all resource records in the zone file
28
33
  def initialize(opts)
29
34
  @domain = opts[:domain]
30
35
  @ns = opts[:ns]
31
- @hostmaster = escape(opts[:hostmaster] || "hostmaster.#{@domain}")
32
- @ttl = Lifetime.new(opts[:ttl] || '1H')
33
- @refresh = Lifetime.new(opts[:refresh] || '1H')
34
- @retry = Lifetime.new(opts[:retry] || '10M')
35
- @expire = Lifetime.new(opts[:expire] || '1D')
36
+ @hostmaster = escape(opts[:hostmaster] || "hostmaster.#{@domain}")
37
+ @ttl = Lifetime.new(opts[:ttl] || '1H')
38
+ @refresh = Lifetime.new(opts[:refresh] || '1H')
39
+ @retry = Lifetime.new(opts[:retry] || '10M')
40
+ @expire = Lifetime.new(opts[:expire] || '1D')
41
+ @negative = Lifetime.new(opts[:negative] || '1H')
36
42
  end
37
43
  # Returns the SOA record with the serial set to the current unix timestamp
38
44
  # @return [String] SOA Record
@@ -52,7 +58,7 @@ module RedZone
52
58
  io << " %-10s ; ref = refresh = %s\n" % [@refresh.seconds,@refresh]
53
59
  io << " %-10s ; rt = retry = %s\n" % [@retry.seconds,@retry]
54
60
  io << " %-10s ; ex = expiry = %s\n" % [@expire.seconds,@expire]
55
- io << " %-10s ; ttl = %s\n" % [@ttl.seconds,@ttl]
61
+ io << " %-10s ; nx = nxdomain ttl = %s\n" % [@negative.seconds,@negative]
56
62
  io << ")\n\n"
57
63
  io.string
58
64
  end
@@ -2,5 +2,5 @@
2
2
  #
3
3
  module RedZone
4
4
  # Current version of RedZone
5
- VERSION = '0.0.1'
5
+ VERSION = '0.0.2'
6
6
  end
data/lib/redzone/zone.rb CHANGED
@@ -155,9 +155,11 @@ module RedZone
155
155
 
156
156
  private
157
157
  def sorted_each(hash,&block)
158
- keys = hash.keys.sort
159
- keys.each do |key|
160
- block.call(key,hash[key])
158
+ unless hash.nil?
159
+ keys = hash.keys.sort
160
+ keys.each do |key|
161
+ block.call(key,hash[key])
162
+ end
161
163
  end
162
164
  end
163
165
  def symbolize(hash)
@@ -268,7 +270,7 @@ module RedZone
268
270
  end
269
271
  def generate_records
270
272
  @records = []
271
- if @config.has_key?('records')
273
+ if @config.has_key?('records') and not @config['records'].nil?
272
274
  @config['records'].each do |record|
273
275
  @records << Record.new(symbolize(record))
274
276
  end
@@ -19,14 +19,11 @@ describe RedZone::Arpa do
19
19
  subject { arpa_ipv4 }
20
20
  its(:name) { should == '32.12.in-addr.arpa'}
21
21
  its(:network) { should == IPAddr.new('12.32.0.0/16') }
22
- its ("to_s") { should eq("") }
23
-
24
22
  end
25
23
  context "ipv6 network" do
26
24
  subject { arpa_ipv6 }
27
25
  its (:name) { should == '9.8.7.6.4.3.2.1.1.0.0.2.ip6.arpa' }
28
26
  its (:network) { should == IPAddr.new('2001:1234:6789::/48') }
29
- it { subject.to_s.should eq("") }
30
27
  end
31
28
  it 'should require name option' do
32
29
  expect { described_class.new({:network => '12.32.0.0/16', :soa => 'soa'})}.to raise_error(ArgumentError,':name is required')
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe RedZone::Zone do
4
+ it "should skip empty mailservers"
5
+ it "should skip empty nameservers"
6
+ it "should skip empty aliases"
7
+ it "should skip empty cnames"
8
+ it "should skip empty default"
9
+ it "should skip empty wildcard"
10
+ it "should skip empty records"
11
+ end
File without changes
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redzone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justen Walker
@@ -65,6 +65,7 @@ extensions: []
65
65
  extra_rdoc_files: []
66
66
  files:
67
67
  - .gitignore
68
+ - .travis.yml
68
69
  - Gemfile
69
70
  - LICENSE.md
70
71
  - README.md
@@ -85,11 +86,11 @@ files:
85
86
  - lib/redzone/zone_config.rb
86
87
  - lib/redzone/zonefile_writer.rb
87
88
  - redzone.gemspec
88
- - redzone.rb
89
89
  - spec/spec_helper.rb
90
90
  - spec/unit/arpa_spec.rb
91
91
  - spec/unit/record_spec.rb
92
- - zones.yml
92
+ - spec/unit/zone_spec.rb
93
+ - zones.yml.example
93
94
  homepage: https://github.com/justenwalker/redzone
94
95
  licenses:
95
96
  - MIT
@@ -118,4 +119,5 @@ test_files:
118
119
  - spec/spec_helper.rb
119
120
  - spec/unit/arpa_spec.rb
120
121
  - spec/unit/record_spec.rb
122
+ - spec/unit/zone_spec.rb
121
123
  has_rdoc:
data/redzone.rb DELETED
@@ -1,279 +0,0 @@
1
- #! /usr/bin/env ruby
2
-
3
- require 'yaml'
4
- require 'tsort'
5
-
6
- class String
7
- def unindent
8
- gsub(/^#{scan(/^\s*/).min_by{|l|l.length}}/, "")
9
- end
10
- end
11
- module RedZone
12
- class ZoneConfig
13
- include TSort
14
- def initialize(zonefile)
15
- @cfg = YAML.load_file(zonefile)
16
- @zones = Hash.new {|h,k| h[k] = []}
17
- @machines = []
18
- @ips = []
19
- @cfg['zones'].each do |k,v|
20
- add(Zone.new(k,v))
21
- end
22
- end
23
- def add(zone)
24
- @zones[zone.name] = zone
25
- end
26
- def tsort_each_node(&block)
27
- @zones.each_key(&block)
28
- end
29
- def tsort_each_child(node, &block)
30
- @zones[node].dependencies.each(&block) if @zones.has_key?(node)
31
- end
32
- def domains
33
- d = []
34
- @zones.each do |k,v|
35
- d << v.domains
36
- end
37
- d.flatten
38
- end
39
- def setup!
40
- self.tsort.each do |z|
41
- zone = @zones[z]
42
- zone.dependencies.each do |dep|
43
- zone.inherit!(@zones[dep])
44
- end
45
- end
46
- end
47
- def generate_domain(domain)
48
- io = StringIO.new
49
- @zones.each do |k,v|
50
- if v.domains.include?(domain)
51
- io << v.generate_zonefile(domain)
52
- end
53
- end
54
- io.string
55
- end
56
- end
57
- class Zone
58
- attr_reader :name,:dependencies,:config
59
- def inherit!(zone)
60
- unless @inherited.include?(zone.name)
61
- @config = zone.config.merge(@config)
62
- @inherited << zone.name
63
- end
64
- end
65
- def initialize(name,config)
66
- @inherited = []
67
- @name = name
68
- @config = config
69
- @dependencies = []
70
- if @config.has_key?('inherits')
71
- @dependencies << @config['inherits']
72
- @dependencies = @dependencies.flatten
73
- end
74
- end
75
- def domains
76
- @config['domains'] || []
77
- end
78
- def generate_conffile(domain,datafile,masters=[])
79
- io = StringIO.new
80
- write_conffile(io,domain,datafile,masters)
81
- io.string
82
- end
83
- def write_conffile(io,domain,datafile,masters=[])
84
- if not masters.empty?
85
- masterlist = masters.join(" ; ")
86
- io << <<-eos.unindent
87
- zone "#{domain}" in {
88
- type slave;
89
- file "#{datafile}";
90
- masters { #{masterlist} ; } ;
91
- }
92
- eos
93
- else
94
- io << <<-eos.unindent
95
- zone "#{domain}" in {
96
- type master;
97
- file "#{datafile}";
98
- }
99
- eos
100
- end
101
- end
102
- def generate_zonefile(domain)
103
- io = StringIO.new
104
- write_zonefile(io,domain)
105
- io.string
106
- end
107
- def write_zonefile(io,domain)
108
- io << generate_soa(domain)
109
- io << generate_default
110
- io << generate_dns
111
- io << generate_mail
112
- io << generate_machines
113
- io << generate_names
114
- io << generate_aliases
115
- io << generate_wildcard
116
- end
117
-
118
- private
119
- def all_machines
120
- machines = []
121
- @config['machines'].each do |name,cfg|
122
- machines << Machine.new(name,cfg)
123
- end
124
- machines
125
- end
126
- def get_machine(name)
127
- Machine.new(name,@config['machines'][name])
128
- end
129
- def generate_soa(domain)
130
- lifetimes = @config['lifetimes']
131
- ttl = lifetimes['ttl']
132
- hostmaster = @config['hostmaster']
133
- now = Time.now.to_i
134
- refresh = lifetimes['refresh']
135
- re = lifetimes['retry']
136
- expire = lifetimes['expire']
137
- negative = lifetimes['negative']
138
- <<-eos.unindent
139
- $ORIGIN #{domain}.
140
- $TTL #{ttl} ; queries are cached for this long
141
- @ IN SOA ns1 #{hostmaster} (
142
- #{now} ; Date $time
143
- #{refresh} ; slave queries for refresh this often
144
- #{re} ; slave retries refresh this often after failure
145
- #{expire} ; slave expires after this long if not refreshed
146
- #{negative} ; errors are cached for this long
147
- )
148
-
149
- eos
150
- end
151
- def generate_record(name,type,detail,value,comment=nil)
152
- suffix = " ; #{comment}" unless comment.nil?
153
- "%-20s IN %-8s %-6s %s%s\n" % [name, type, detail, value, suffix || ""]
154
- end
155
- def generate_machine(name,machine)
156
- comment = "Machine #{machine}" unless name == machine
157
- if machine.is_a? String
158
- machine = get_machine(machine)
159
- end
160
- io = StringIO.new
161
- io << generate_record(name,"A","",machine.ipv4,comment) if machine.ipv4?
162
- io << generate_record(name,"AAAA","",machine.ipv6,comment) if machine.ipv6?
163
- io.string
164
- end
165
- def generate_default
166
- io = StringIO.new
167
- if @config['default']
168
- io << "; Primary name records for unqualfied domain\n"
169
- io << generate_machine("@",@config['default'])
170
- io << "\n"
171
- end
172
- io.string
173
- end
174
- def generate_dns
175
- io = StringIO.new
176
- if @config.has_key?('dns')
177
- io << ": DNS Server Records\n"
178
- dns_keys = @config['dns'].keys.sort
179
- dns_keys.each do |k|
180
- io << generate_record("@","NS","",k)
181
- end
182
- dns_keys.each do |k|
183
- machine = @config['dns'][k]
184
- io << generate_machine(k,machine)
185
- end
186
- io << "\n"
187
- end
188
- io.string
189
- end
190
- def generate_mail
191
- io = StringIO.new
192
- if @config.has_key?('mail')
193
- io << "; Email Servers\n"
194
- mail_keys = @config['mail'].keys.sort
195
- mail_keys.each do |k|
196
- mail = @config['mail'][k]
197
- priority = mail['priority']
198
- io << generate_record("@","MX",priority,k)
199
- end
200
- mail_keys.each do |k|
201
- mail = @config['mail'][k]
202
- machine = mail['machine']
203
- io << generate_machine(k,machine)
204
- end
205
- io << "\n"
206
- end
207
- io.string
208
- end
209
- def generate_machines
210
- io = StringIO.new
211
- io << "; Primary Machine Names\n"
212
- all_machines.each do |machine|
213
- io << generate_machine(machine.name,machine)
214
- end
215
- io << "\n"
216
- io.string
217
- end
218
- def generate_names
219
- io = StringIO.new
220
- if @config.has_key?('mail')
221
- io << "; Extra Names\n"
222
- name_keys = @config['names'].keys.sort
223
- name_keys.each do |name|
224
- machine = @config['names'][name]
225
- io << generate_machine(name,machine)
226
- end
227
- io << "\n"
228
- end
229
- io.string
230
- end
231
- def generate_aliases
232
- io = StringIO.new
233
- if @config.has_key?('mail')
234
- io << "; Extra Names\n"
235
- cname_keys = @config['aliases'].keys.sort
236
- cname_keys.each do |cname|
237
- value = @config['aliases'][cname]
238
- io << generate_record(cname,"CNAME","",value)
239
- end
240
- io << "\n"
241
- end
242
- io.string
243
- end
244
- def generate_wildcard
245
- io = StringIO.new
246
- if @config['wildcard']
247
- io << "; Wildcard\n"
248
- io << generate_machine("*",@config['wildcard'])
249
- io << "\n"
250
- end
251
- io.string
252
- end
253
- end
254
- class Machine
255
- attr_reader :name,:ipv4,:ipv6
256
- def initialize(name,config)
257
- @name = name
258
- @ipv4 = config['ipv4']
259
- @ipv6 = config['ipv6']
260
- end
261
- def ipv4?
262
- not @ipv4.nil?
263
- end
264
- def ipv6?
265
- not @ipv6.nil?
266
- end
267
- def to_s
268
- @name
269
- end
270
- end
271
- end
272
-
273
- zonecfg = RedZone::ZoneConfig.new 'zones.yml'
274
- zonecfg.setup!
275
- zonecfg.domains.each do |d|
276
- puts zonecfg.generate_domain(d)
277
- end
278
-
279
-