em-powerdns 0.0.1
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.
- 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
|
+
|