em-powerdns 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/Gemfile +20 -0
- data/LICENSE +20 -0
- data/README.rdoc +36 -0
- data/Rakefile +86 -0
- data/VERSION +1 -0
- data/lib/em-powerdns.rb +139 -0
- data/tasks/powerdns.rake +219 -0
- metadata +81 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
source :gemcutter
|
2
|
+
|
3
|
+
group :runtime do
|
4
|
+
gem 'eventmachine'
|
5
|
+
end
|
6
|
+
|
7
|
+
group :release do
|
8
|
+
gem 'jeweler'
|
9
|
+
gem 'rake'
|
10
|
+
gem 'bundler', '~> 0.9.11'
|
11
|
+
end
|
12
|
+
|
13
|
+
group :test do
|
14
|
+
gem 'rspec', '>= 1.2.9', :require => 'spec'
|
15
|
+
gem 'reek'
|
16
|
+
gem 'roodi'
|
17
|
+
gem 'yard'
|
18
|
+
gem 'ruby-debug'
|
19
|
+
gem 'sys-uname'
|
20
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Martin Emde
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
= em-powerdns
|
2
|
+
|
3
|
+
You can use this plus the unix program PowerDNS to make a custom DNS server
|
4
|
+
with the lookup done by a ruby script you write.
|
5
|
+
|
6
|
+
Even though the actual PowerDNS pipe backend is synchronous, using this will
|
7
|
+
allow a script to start up other side tasks, logging or stats for example,
|
8
|
+
without interrupting the scripts ability to serve more requests.
|
9
|
+
|
10
|
+
Include EM::P::PowerDNS in a module or class to use it as a PowerDNS backend.
|
11
|
+
|
12
|
+
== Example
|
13
|
+
|
14
|
+
module RedisBackend
|
15
|
+
include EM::P::PowerDNS
|
16
|
+
|
17
|
+
def receive_query(query)
|
18
|
+
# make some logic here to resolve the DNS
|
19
|
+
ip = redis[query.qname]
|
20
|
+
data query.qname, query.qclass, :A, 3600, 1, ip
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def redis
|
25
|
+
@redis ||= Redis.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
EM.run { EM.open_keyboard(RedisBackend) }
|
30
|
+
|
31
|
+
PowerDNS uses stdin to send all it's queries so EM.open_keyboard does exactly
|
32
|
+
what we need.
|
33
|
+
|
34
|
+
== Copyright
|
35
|
+
|
36
|
+
Copyright (c) 2010 Martin Emde. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
Bundler.require
|
4
|
+
|
5
|
+
load 'tasks/powerdns.rake'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gem|
|
10
|
+
gem.name = "em-powerdns"
|
11
|
+
gem.summary = %Q{Ruby EventMachine PowerDNS Protocol for PDNS custom pipe backend}
|
12
|
+
gem.description = gem.summary
|
13
|
+
gem.email = "martin.emde@gmail.com"
|
14
|
+
gem.homepage = "http://github.com/martinemde/em-powerdns"
|
15
|
+
gem.authors = ["Martin Emde"]
|
16
|
+
|
17
|
+
bundle = Bundler::Definition.from_gemfile('Gemfile')
|
18
|
+
bundle.dependencies.each do |dep|
|
19
|
+
gem.add_dependency(dep.name, dep.requirement.to_s) if dep.groups.include?(:runtime)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
Jeweler::GemcutterTasks.new
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'spec/rake/spectask'
|
28
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
30
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
31
|
+
end
|
32
|
+
|
33
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
34
|
+
spec.libs << 'lib' << 'spec'
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
spec.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
require 'cucumber/rake/task'
|
41
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
42
|
+
t.cucumber_opts = %w{--guess}
|
43
|
+
end
|
44
|
+
|
45
|
+
task :features => :check_dependencies
|
46
|
+
rescue LoadError
|
47
|
+
task :features do
|
48
|
+
abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
task :default => %w[spec features]
|
53
|
+
|
54
|
+
begin
|
55
|
+
require 'reek/adapters/rake_task'
|
56
|
+
Reek::RakeTask.new do |t|
|
57
|
+
t.fail_on_error = true
|
58
|
+
t.verbose = false
|
59
|
+
t.source_files = 'lib/**/*.rb'
|
60
|
+
end
|
61
|
+
rescue LoadError
|
62
|
+
task :reek do
|
63
|
+
abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
begin
|
68
|
+
require 'roodi'
|
69
|
+
require 'roodi_task'
|
70
|
+
RoodiTask.new do |t|
|
71
|
+
t.verbose = false
|
72
|
+
end
|
73
|
+
rescue LoadError
|
74
|
+
task :roodi do
|
75
|
+
abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
begin
|
80
|
+
require 'yard'
|
81
|
+
YARD::Rake::YardocTask.new
|
82
|
+
rescue LoadError
|
83
|
+
task :yardoc do
|
84
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
85
|
+
end
|
86
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/lib/em-powerdns.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
# Instances of this class wrap the PowerDNS I/O stream with a nice API
|
4
|
+
module EventMachine::Protocols
|
5
|
+
module PowerDNS
|
6
|
+
class Error < RuntimeError
|
7
|
+
attr_reader :original_exception
|
8
|
+
|
9
|
+
def initialize(data, exception)
|
10
|
+
@original_exception = exception
|
11
|
+
super "Unexpected error in the EM::P::PowerDNS:\nPowerDNS Data: #{data.inspect}\nError: #{exception}\n#{exception.backtrace}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
include EM::Protocols::LineText2
|
16
|
+
include Output
|
17
|
+
|
18
|
+
SEPARATOR = "\t"
|
19
|
+
EVENT_MAP = Hash.new(:receive_garbage)
|
20
|
+
EVENT_MAP.update(
|
21
|
+
'HELO' => :receive_raw_handshake,
|
22
|
+
'Q' => :receive_raw_query,
|
23
|
+
'AXFR' => :receive_raw_axfr,
|
24
|
+
'PING' => :receive_raw_ping
|
25
|
+
)
|
26
|
+
|
27
|
+
def self.start
|
28
|
+
EM.open_keyboard(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
$stdin.sync = true
|
33
|
+
$stdout.sync = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def receive_line(data)
|
37
|
+
parts = data.split SEPARATOR
|
38
|
+
type = parts.shift
|
39
|
+
send EVENT_MAP[type], *parts
|
40
|
+
rescue => e
|
41
|
+
receive_error Error.new(data, e)
|
42
|
+
end
|
43
|
+
|
44
|
+
def receive_raw_handshake(*parts)
|
45
|
+
@version = parts.first.to_i
|
46
|
+
if [1,2].include?(@version)
|
47
|
+
receive_handshake(@version)
|
48
|
+
else
|
49
|
+
fail "Received unexpected handshake: #{parts.inspect}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def receive_handshake(version)
|
54
|
+
ok "Backend starting version #{version}."
|
55
|
+
end
|
56
|
+
|
57
|
+
class Query < Struct.new(:qname, :qclass, :qtype, :id, :remote_ip, :local_ip)
|
58
|
+
end
|
59
|
+
|
60
|
+
def receive_raw_query(*parts)
|
61
|
+
if parts.size != parts_size_for_version
|
62
|
+
fail "Received unexpected format for Q: #{parts.inspect}"
|
63
|
+
else
|
64
|
+
query = Query.new(*parts)
|
65
|
+
receive_query(query)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def parts_size_for_version
|
70
|
+
@version == 1 ? 5 : 6 # already chopped off the 'Q'
|
71
|
+
end
|
72
|
+
|
73
|
+
# Stub method for users implementing this protocol
|
74
|
+
def receive_query(query)
|
75
|
+
done
|
76
|
+
end
|
77
|
+
|
78
|
+
def receive_raw_axfr(*parts)
|
79
|
+
if parts.size != 1
|
80
|
+
fail "Received unexpected format for AXFR: #{parts.inspect}"
|
81
|
+
else
|
82
|
+
receive_axfr(parts.first)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Stub method for users implementing this protocol
|
87
|
+
def receive_axfr(soa_resource)
|
88
|
+
done
|
89
|
+
end
|
90
|
+
|
91
|
+
def receive_raw_ping(*parts)
|
92
|
+
receive_ping
|
93
|
+
end
|
94
|
+
|
95
|
+
# Stub method for users implementing this protocol
|
96
|
+
def receive_ping
|
97
|
+
done
|
98
|
+
end
|
99
|
+
|
100
|
+
def receive_garbage(line)
|
101
|
+
fail "Unknown Question: #{line.inspect}"
|
102
|
+
end
|
103
|
+
|
104
|
+
def receive_error(error)
|
105
|
+
fail "An unexpected error occurred in backend: #{error.original_exception.message}"
|
106
|
+
raise error
|
107
|
+
end
|
108
|
+
module Output
|
109
|
+
def ok(line)
|
110
|
+
send_line "OK", line
|
111
|
+
end
|
112
|
+
|
113
|
+
def data(*parts)
|
114
|
+
send_line "DATA", *parts
|
115
|
+
end
|
116
|
+
|
117
|
+
def log(line)
|
118
|
+
send_line "LOG", line
|
119
|
+
end
|
120
|
+
|
121
|
+
def fail(line = nil)
|
122
|
+
log(line) if line
|
123
|
+
send_line "FAIL"
|
124
|
+
end
|
125
|
+
|
126
|
+
def done(line = nil)
|
127
|
+
log(line) if line
|
128
|
+
send_line "END"
|
129
|
+
end
|
130
|
+
|
131
|
+
def send_line(*parts)
|
132
|
+
send_data parts.join(PowerDNS::Connection::SEPARATOR)
|
133
|
+
end
|
134
|
+
|
135
|
+
def send_data(data)
|
136
|
+
$stdout.puts data
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/tasks/powerdns.rake
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
# Inspired by powerdns, which was inspired by rabbitmq.rake the Redbox project at http://github.com/rick/redbox/tree/master
|
2
|
+
require 'rake'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pathname'
|
5
|
+
require 'sys/uname'
|
6
|
+
|
7
|
+
class PDNS
|
8
|
+
SOURCE_URI = "http://downloads.powerdns.com/releases/pdns-2.9.22.tar.gz"
|
9
|
+
BOOST_URI = "http://downloads.sourceforge.net/project/boost/boost/1.42.0/boost_1_42_0.tar.gz?use_mirror=superb-sea2"
|
10
|
+
DTACH_URI = "http://downloads.sourceforge.net/project/dtach/dtach/0.8/dtach-0.8.tar.gz"
|
11
|
+
ROOT = (Pathname.new(File.dirname(__FILE__)) + '../powerdns').cleanpath
|
12
|
+
PDNS_SERVER = 'pdns_server'
|
13
|
+
BACKEND = 'backend'
|
14
|
+
|
15
|
+
def self.bin() ROOT + 'bin' end
|
16
|
+
def self.etc() ROOT + 'etc' end
|
17
|
+
def self.src() ROOT + 'src' end
|
18
|
+
def self.tmp() ROOT + 'tmp' end
|
19
|
+
|
20
|
+
def self.source_path() src + 'powerdns' end
|
21
|
+
def self.compiled_path() source_path + 'pdns' end
|
22
|
+
def self.boost_path() src + 'boost' end
|
23
|
+
|
24
|
+
def self.server_command() bin + PDNS_SERVER end
|
25
|
+
def self.pipe_command() bin + BACKEND end
|
26
|
+
def self.config() etc + 'pdns.conf' end
|
27
|
+
|
28
|
+
def self.dtach_socket
|
29
|
+
tmp.mkpath
|
30
|
+
tmp + 'powerdns.dtach'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Just check for existance of dtach socket
|
34
|
+
def self.running?
|
35
|
+
File.exists? dtach_socket
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.start
|
39
|
+
puts 'Detach with Ctrl+\ Re-attach with rake powerdns:attach'
|
40
|
+
sleep 3
|
41
|
+
exec "dtach -A #{dtach_socket} #{server_command}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.start_detached
|
45
|
+
system "dtach -n #{dtach_socket} #{server_command}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.attach
|
49
|
+
exec "dtach -a #{dtach_socket}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.stop
|
53
|
+
system 'echo "SHUTDOWN" | nc localhost 6379'
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
namespace :powerdns do
|
59
|
+
|
60
|
+
desc 'About powerdns'
|
61
|
+
task :about do
|
62
|
+
puts "\nSee http://www.powerdns.com/ for information about PowerDNS.\n\n"
|
63
|
+
end
|
64
|
+
|
65
|
+
desc 'Start powerdns'
|
66
|
+
task :start do
|
67
|
+
PDNS.start
|
68
|
+
end
|
69
|
+
|
70
|
+
desc 'Stop powerdns'
|
71
|
+
task :stop do
|
72
|
+
PDNS.stop
|
73
|
+
end
|
74
|
+
|
75
|
+
desc 'Restart powerdns'
|
76
|
+
task :restart do
|
77
|
+
PDNS.stop
|
78
|
+
PDNS.start
|
79
|
+
end
|
80
|
+
|
81
|
+
desc 'Attach to powerdns dtach socket'
|
82
|
+
task :attach do
|
83
|
+
PDNS.attach
|
84
|
+
end
|
85
|
+
|
86
|
+
desc 'Install PowerDNS server and configuration file'
|
87
|
+
task :install => %w[about install:server install:backend install:config]
|
88
|
+
|
89
|
+
namespace :install do
|
90
|
+
desc 'Install PowerDNS server'
|
91
|
+
task :server => [:paths] do
|
92
|
+
script = PDNS.server_command
|
93
|
+
script.delete if script.exist?
|
94
|
+
script.open('w') do |f|
|
95
|
+
f.puts <<-SCRIPT
|
96
|
+
#!/bin/bash
|
97
|
+
sudo #{PDNS.compiled_path.realpath + PDNS::PDNS_SERVER} --config-dir=#{PDNS.etc}
|
98
|
+
SCRIPT
|
99
|
+
end
|
100
|
+
script.chmod(0755)
|
101
|
+
puts "Installed #{script}."
|
102
|
+
end
|
103
|
+
|
104
|
+
desc 'Install PowerDNS config'
|
105
|
+
task :config => [:backend, :paths] do
|
106
|
+
config = PDNS.config
|
107
|
+
config.delete if config.exist?
|
108
|
+
config.open('w') do |file|
|
109
|
+
file.puts <<-CONFIG
|
110
|
+
launch=pipe
|
111
|
+
pipe-command=#{PDNS.pipe_command}
|
112
|
+
pipebackend-abi-version=2
|
113
|
+
CONFIG
|
114
|
+
end
|
115
|
+
`cat #{PDNS.compiled_path.realpath + 'pdns.conf-dist'} >> #{config}`
|
116
|
+
puts "Installed #{config} and configured it for testing.\n You should double check this file."
|
117
|
+
end
|
118
|
+
|
119
|
+
desc 'Install backend wrapper'
|
120
|
+
task :backend => [:paths] do
|
121
|
+
gem_root = File.expand_path('../..', __FILE__)
|
122
|
+
pipe = PDNS.pipe_command
|
123
|
+
pipe.delete if pipe.exist?
|
124
|
+
pipe.open('w') do |f|
|
125
|
+
f.puts <<-SCRIPT
|
126
|
+
#!/bin/bash
|
127
|
+
cd #{gem_root}
|
128
|
+
bundle exec bin/backend
|
129
|
+
SCRIPT
|
130
|
+
end
|
131
|
+
pipe.chmod(0755)
|
132
|
+
puts "Linked #{pipe} to #{executable}."
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
desc "Configure and make PowerDNS"
|
137
|
+
task :make => [:paths, :download, :boost] do
|
138
|
+
cflags = "-I#{PDNS.boost_path.realpath}"
|
139
|
+
cflags << " -DDARWIN" if Sys::Uname.sysname =~ /Darwin/i
|
140
|
+
|
141
|
+
system <<-COMMAND
|
142
|
+
cd #{PDNS.source_path}
|
143
|
+
|
144
|
+
echo "Configuring PowerDNS for pipe backend ..."
|
145
|
+
CXXFLAGS="#{cflags}" ./configure --with-modules=pipe --without-pgsql --without-mysql --without-sqlite --without-sqlite3
|
146
|
+
|
147
|
+
echo "make clean ..."
|
148
|
+
make clean
|
149
|
+
|
150
|
+
echo "make ..."
|
151
|
+
make
|
152
|
+
COMMAND
|
153
|
+
end
|
154
|
+
|
155
|
+
desc "Download PowerDNS source"
|
156
|
+
task :download => [:paths, :boost] do
|
157
|
+
source_path = PDNS.source_path
|
158
|
+
unless source_path.exist?
|
159
|
+
source_path.mkpath
|
160
|
+
puts "Downloading PowerDNS source..."
|
161
|
+
system "curl -L #{PDNS::SOURCE_URI} | tar zx --strip-components 1 -C #{source_path}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
desc "PowerDNS requires boost libs at compile time"
|
166
|
+
task :boost => :paths do
|
167
|
+
boost_path = PDNS.boost_path
|
168
|
+
unless boost_path.exist?
|
169
|
+
boost_path.mkpath
|
170
|
+
puts "Downloading Boost source..."
|
171
|
+
system "curl -L #{PDNS::BOOST_URI} | tar zx --strip-components 1 -C #{boost_path}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
task :paths do
|
176
|
+
[PDNS.bin, PDNS.etc, PDNS.src].each { |path| path.mkpath }
|
177
|
+
end
|
178
|
+
|
179
|
+
namespace :purge do
|
180
|
+
def purge(*paths)
|
181
|
+
paths.each do |path|
|
182
|
+
path.rmtree if path.exist?
|
183
|
+
path.mkpath
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
task :installs do
|
188
|
+
purge(PDNS.bin, PDNS.etc)
|
189
|
+
end
|
190
|
+
|
191
|
+
task :src do
|
192
|
+
purge(PDNS.src)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
namespace :dtach do
|
198
|
+
desc 'About dtach'
|
199
|
+
task :about do
|
200
|
+
puts <<-ABOUT
|
201
|
+
dtach allows background proccess that are not attached to a term.
|
202
|
+
See http://dtach.sourceforge.net/ for more information about dtach.
|
203
|
+
|
204
|
+
ABOUT
|
205
|
+
end
|
206
|
+
|
207
|
+
desc 'Install dtach 0.8 from source'
|
208
|
+
task :install => [:about] do
|
209
|
+
dtach_path = PDNS.source_path + 'dtach'
|
210
|
+
|
211
|
+
unless dtach.exist?
|
212
|
+
dtach.mkpath
|
213
|
+
system "curl -L #{PDNS::DTACH_URI} | tar zx --strip-components 1 -C #{dtach_path}"
|
214
|
+
end
|
215
|
+
|
216
|
+
system "cd #{dtach_path} && ./configure && make && ln -s dtach #{PDNS.bin + 'dtach'}"
|
217
|
+
puts "dtach installed to #{PDNS.bin}."
|
218
|
+
end
|
219
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: em-powerdns
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Martin Emde
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-10 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: eventmachine
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
description: Ruby EventMachine PowerDNS Protocol for PDNS custom pipe backend
|
33
|
+
email: martin.emde@gmail.com
|
34
|
+
executables: []
|
35
|
+
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files:
|
39
|
+
- LICENSE
|
40
|
+
- README.rdoc
|
41
|
+
files:
|
42
|
+
- .gitignore
|
43
|
+
- Gemfile
|
44
|
+
- LICENSE
|
45
|
+
- README.rdoc
|
46
|
+
- Rakefile
|
47
|
+
- VERSION
|
48
|
+
- lib/em-powerdns.rb
|
49
|
+
- tasks/powerdns.rake
|
50
|
+
has_rdoc: true
|
51
|
+
homepage: http://github.com/martinemde/em-powerdns
|
52
|
+
licenses: []
|
53
|
+
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options:
|
56
|
+
- --charset=UTF-8
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.6
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Ruby EventMachine PowerDNS Protocol for PDNS custom pipe backend
|
80
|
+
test_files: []
|
81
|
+
|