pdns_api 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e775769016b6af7782ddfa3baec55322b779ef01
4
+ data.tar.gz: a782baf51327ab968e84dfb96d1460caf2623df1
5
+ SHA512:
6
+ metadata.gz: e58156e4d03ee86e35cded0a95b35b6210d0c6af8294fc6618aaa818cf4cbe04df7b5e606aa2c9d0ba8b732c8a4e578d8adfc1ca1e1ed68ee563aae962c25696
7
+ data.tar.gz: ddc4ba236a91245518f8bb751a62efdcaf3912167435b5da82b63d0c0ccc5fbe80b87d84d380219807d429fa95bc40102efee8d9024c6a8d76eb23b974ebb507
@@ -0,0 +1,55 @@
1
+ require 'pdns_api/http'
2
+
3
+ # PDNS API interface
4
+ module PDNS
5
+ # Class for interacting with the API
6
+ class API
7
+ def initialize(args)
8
+ @version = args.key?(:version) ? args[:version] : 1
9
+ @http = PDNS::HTTP.new(args)
10
+ @url = @http.uri
11
+ @r_url = @url
12
+ @info = {}
13
+ end
14
+
15
+ ## Standard manipulation methods
16
+
17
+ # Get information for this object
18
+ def get
19
+ @info = @http.get @url
20
+ end
21
+
22
+ # Delete this object
23
+ def delete
24
+ @http.delete @url
25
+ end
26
+
27
+ # Create this object on the server
28
+ def create(info = nil)
29
+ info(info)
30
+ @http.post(@r_url, @info)
31
+ end
32
+
33
+ # Get/set info
34
+ def info(info = nil)
35
+ return @info if info.nil?
36
+
37
+ @info.merge!(info)
38
+ end
39
+
40
+ ## Helper methods
41
+
42
+ def ensure_array(item)
43
+ return item if item.is_a? Array
44
+ [item]
45
+ end
46
+
47
+ def self.hash_sym_to_string(hash)
48
+ hash.map { |symbol, value| [symbol.to_s, value] }.to_h
49
+ end
50
+
51
+ def self.hash_string_to_sym(hash)
52
+ hash.map { |string, value| [string.to_sym, value] }.to_h
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,22 @@
1
+ require 'pdns_api/version'
2
+ require 'pdns_api/api'
3
+ require 'pdns_api/server'
4
+
5
+ # PDNS client
6
+ module PDNS
7
+ # Client
8
+ class Client < API
9
+ attr_reader :version
10
+
11
+ ## Main methods
12
+ def servers(id = nil)
13
+ return Server.new(@http, @url, id) unless id.nil?
14
+
15
+ # Return a hash of server objects
16
+ servers = @http.get "#{@url}/servers"
17
+ servers.map! { |s| [s[:id], Server.new(@url, s[:id], s)] }.to_h
18
+ end
19
+
20
+ alias server servers
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ # PDNS Server config
2
+ module PDNS
3
+ # Server config
4
+ class Config < API
5
+ attr_accessor :name, :value
6
+
7
+ def initialize(http, t_url, name, value = nil)
8
+ @http = http
9
+ @name = name
10
+ @r_url = "#{t_url}/config"
11
+ @url = "#{t_url}/config/#{name}"
12
+ @value = value.get if value.nil?
13
+ value(value)
14
+ end
15
+
16
+ ## Simple interfaces to metadata
17
+ # Get/set config value
18
+ def value(value = nil)
19
+ return @info[:value] if value.nil?
20
+ @info = { type: 'ConfigSetting', namen: @name, value: value }
21
+ end
22
+
23
+ # Get configuration value
24
+ def get
25
+ res = @http.get(@url)
26
+ return value if res.key? :value
27
+ end
28
+
29
+ # Change configuration
30
+ def change(value = nil)
31
+ value(value)
32
+ @http.put(@url, @info)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ # PDNS Zone CryptoKeys
2
+ module PDNS
3
+ # Zone CryptoKey
4
+ class CryptoKey < API
5
+ def initialize(http, t_url, id, info = {})
6
+ @http = http
7
+ @id = id
8
+ @info = info
9
+ @r_url = "#{t_url}/metadata"
10
+ @url = "#{t_url}/metadata/#{kind}"
11
+ end
12
+
13
+ ## Simple interfaces to metadata
14
+
15
+ # Change cryptokey information
16
+ def change(rrsets)
17
+ @http.put(@url, rrsets)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,89 @@
1
+ # PDNS HTTP API interface
2
+ module PDNS
3
+ # Class for doing HTTP requests
4
+ class HTTP
5
+ attr_accessor :headers
6
+
7
+ def initialize(args)
8
+ @host = args[:host]
9
+ @key = args[:key]
10
+ @port = args.key?(:port) ? args[:port] : 8081
11
+ @version = args.key?(:version) ? args[:version] : 1
12
+ @headers = { 'X-API-Key' => @key }
13
+ end
14
+
15
+ def uri(request = '')
16
+ base = ''
17
+ base = "/api/v#{@version}" unless @version == 0 || request[0..4] == '/api/'
18
+ base + request
19
+ end
20
+
21
+ # Create the right method object
22
+ def http_method(method, uri)
23
+ # Create the right request
24
+ case method
25
+ when 'GET' then Net::HTTP::Get.new(uri, @headers)
26
+ when 'PATCH' then Net::HTTP::Patch.new(uri, @headers)
27
+ when 'POST' then Net::HTTP::Post.new(uri, @headers)
28
+ when 'PUT' then Net::HTTP::Put.new(uri, @headers)
29
+ when 'DELETE' then Net::HTTP::Delete.new(uri, @headers)
30
+ else abort('Unknown method: ' + method)
31
+ end
32
+ end
33
+
34
+ def response_decode(response)
35
+ return {} if response.body.nil?
36
+
37
+ # Parse and return JSON
38
+ begin
39
+ JSON.parse(response.body, symbolize_names: true)
40
+ rescue JSON::ParserError
41
+ { error: 'Non-JSON response', result: response.body }
42
+ end
43
+ end
44
+
45
+ # Do an HTTP request
46
+ def http(method, request, body = nil)
47
+ # Start an HTTP connection
48
+ begin
49
+ response = Net::HTTP.start(@host, @port) do |http|
50
+ # Create uri & request
51
+ uri = uri(request)
52
+ req = http_method(method, uri)
53
+
54
+ # Do the request
55
+ http.request(req, body.to_json)
56
+ end
57
+ rescue StandardError, Timeout::Error => e
58
+ abort("Error: #{e}")
59
+ end
60
+
61
+ response_decode(response)
62
+ end
63
+
64
+ # Do a DELETE request
65
+ def delete(uri)
66
+ http('DELETE', uri)
67
+ end
68
+
69
+ # Do a GET request
70
+ def get(uri)
71
+ http('GET', uri)
72
+ end
73
+
74
+ # Do a PATCH request
75
+ def patch(uri, body = nil)
76
+ http('PATCH', uri, body)
77
+ end
78
+
79
+ # Do a POST request
80
+ def post(uri, body = nil)
81
+ http('POST', uri, body)
82
+ end
83
+
84
+ # Do a PUT request
85
+ def put(uri, body = nil)
86
+ http('PUT', uri, body)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,38 @@
1
+ # PDNS Zone Metadata
2
+ module PDNS
3
+ # Zone Metadata
4
+ class Metadata < API
5
+ def initialize(http, t_url, kind, info = {})
6
+ @http = http
7
+ @kind = kind
8
+ @info = info
9
+ @r_url = "#{t_url}/metadata"
10
+ @url = "#{t_url}/metadata/#{kind}"
11
+ end
12
+
13
+ ## Simple interfaces to metadata
14
+
15
+ # Set the metadata value
16
+ def value(value = nil)
17
+ return @info[:metadata] if value.nil?
18
+
19
+ # Convert to array if value is string
20
+ value = [value] if value.is_a? String
21
+
22
+ # Set info
23
+ @info = { type: 'Metadata', kind: @kind, metadata: value }
24
+ end
25
+
26
+ # Retrieve metadata value
27
+ def get
28
+ res = @http.get @url
29
+ return value if res.key? :value
30
+ end
31
+
32
+ # Change metadata
33
+ def change(value)
34
+ value(value)
35
+ @http.put(@url, @info)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ # PDNS Server Override
2
+ module PDNS
3
+ # Server override
4
+ class Override < API
5
+ attr_reader :id, :url, :info
6
+
7
+ def initialize(http, t_url, id, info = {})
8
+ @http = http
9
+ @id = id
10
+ @info = info
11
+ @r_url = "#{t_url}/metadata"
12
+ @url = "#{t_url}/metadata/#{kind}"
13
+ end
14
+
15
+ ## Simple interfaces to overrides
16
+
17
+ # Change override settings
18
+ def change(rrsets)
19
+ @http.put(@url, rrsets)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,75 @@
1
+ require 'pdns_api/config'
2
+ require 'pdns_api/override'
3
+ require 'pdns_api/zone'
4
+
5
+ # PDNS Server
6
+ module PDNS
7
+ # PDNS Server
8
+ class Server < API
9
+ attr_reader :id, :url
10
+
11
+ def initialize(http, t_url, id, info = {})
12
+ @http = http
13
+ @id = id
14
+ @r_url = "#{t_url}/servers"
15
+ @url = "#{t_url}/servers/#{id}"
16
+ @info = info
17
+ end
18
+
19
+ ## Server interfaces
20
+ # TODO: /servers/:server_id: ?
21
+
22
+ ## Server actions
23
+
24
+ def cache(domain)
25
+ # TODO: #{url}/cache/flush?domain=:domain: PUT
26
+ end
27
+
28
+ def search_log(search_term)
29
+ # TODO: /servers/:server_id/search-log?q=:search_term: GET
30
+ end
31
+
32
+ def statistics
33
+ # TODO: /servers/:server_id/statistics: GET
34
+ end
35
+
36
+ def trace
37
+ # TODO: /servers/:server_id/trace: GET, PUT
38
+ end
39
+
40
+ def failures
41
+ # TODO: /servers/:server_id/failures: GET, PUT
42
+ end
43
+
44
+ ## Server resources
45
+
46
+ # Get or set server config
47
+ def config(name = nil, value = nil)
48
+ return Config.new(@http, @url, name, value).create unless name.nil? || value.nil?
49
+ return Config.new(@http, @url, name) unless name.nil?
50
+
51
+ # Get all current configuration
52
+ config = @http.get("#{@url}/config")
53
+ config.map { |c| [c[:name], c[:value]] }.to_h
54
+ end
55
+
56
+ # Get or set server overrides, not yet implemented
57
+ def overrides(id = nil)
58
+ return Override.new(@http, @url, id) unless id.nil?
59
+
60
+ overrides = @http.get("#{@url}/config")
61
+ overrides.map { |o| [o[:id], Override.new(@http, @url, o[:id], o)] }.to_h
62
+ end
63
+
64
+ # Get zones or create one
65
+ def zones(zone_id = nil)
66
+ return Zone.new(@http, @url, zone_id) unless zone_id.nil?
67
+
68
+ zones = @http.get("#{@url}/zones")
69
+ zones.map { |z| [z[:id], Zone.new(@http, @url, z[:id], z)] }.to_h
70
+ end
71
+
72
+ alias override overrides
73
+ alias zone zones
74
+ end
75
+ end
@@ -0,0 +1,4 @@
1
+ # PDNS version
2
+ module PDNS
3
+ VERSION = '0.0.4'.freeze
4
+ end
@@ -0,0 +1,184 @@
1
+ # PDNS Zone
2
+ module PDNS
3
+ require_relative 'metadata'
4
+ require_relative 'cryptokey'
5
+
6
+ # Zone
7
+ class Zone < API
8
+ attr_reader :id, :url
9
+
10
+ def initialize(http, t_url, id, info = {})
11
+ @http = http
12
+ @id = id
13
+ @info = info
14
+ @r_url = "#{t_url}/zones"
15
+ @url = "#{t_url}/zones/#{id}"
16
+ end
17
+
18
+ ## Zone interfaces
19
+
20
+ # Modifies present RRsets and comments.
21
+ def modify(rrsets)
22
+ rrsets.map! { |rrset| format_records(rrset) if rrset.key?(:records) }
23
+
24
+ @http.patch(@url, rrsets: rrsets)
25
+ end
26
+
27
+ # Modifies basic zone data (metadata).
28
+ def change(rrsets)
29
+ @http.put(@url, rrsets)
30
+ end
31
+
32
+ ## Zone actions
33
+
34
+ # Notify slaves for a zone
35
+ def notify
36
+ @http.put "#{@url}/notify"
37
+ end
38
+
39
+ # Get the AXFR for a zone
40
+ def axfr_retrieve
41
+ @http.put "#{@url}/axfr-retrieve"
42
+ end
43
+
44
+ # Export a zone
45
+ def export
46
+ @http.get "#{@url}/export"
47
+ end
48
+
49
+ # Check a zone
50
+ def check
51
+ @http.get "#{@url}/check"
52
+ end
53
+
54
+ ## Zone resources
55
+
56
+ # Manipulate metadata for a zone
57
+ def metadata(kind = nil, value = nil)
58
+ return Metadata.new(@http, @url, kind, value).create unless kind.nil? || value.nil?
59
+ return Metadata.new(@http, @url, kind) unless kind.nil?
60
+
61
+ # Get all current metadata
62
+ metadata = @http.get("#{@url}/metadata")
63
+
64
+ # Check for errors
65
+ return metadata if metadata.is_a?(Hash) && metadata.key?(:error)
66
+
67
+ # Convert metadata to hash
68
+ metadata.map! { |c| [c[:kind], c[:metadata]] }.to_h
69
+ end
70
+
71
+ # Change cryptokeys for a zone
72
+ def cryptokeys(id = nil)
73
+ return CryptoKey.new(@http, @url, id) unless id.nil?
74
+
75
+ # Get all current metadata
76
+ cryptokeys = @http.get("#{@url}/cryptokeys")
77
+
78
+ # Convert cryptokeys to hash
79
+ cryptokeys.map! { |c| [c[:id], CryptoKey.new(@http, @url, c[:id], c)] }.to_h
80
+ end
81
+
82
+ ## Additional methods
83
+
84
+ def format_single_record(record)
85
+ # Ensure content
86
+ record = { content: record } if record.is_a? String
87
+
88
+ # Add disabled and set_ptr
89
+ record[:disabled] = !!record[:disabled]
90
+ record[:set_ptr] = !!record[:set_ptr]
91
+
92
+ # Replace some symbols
93
+ record[:'set-ptr'] = record.delete :set_ptr
94
+ record
95
+ end
96
+
97
+ # Add required items to records in an rrset
98
+ def format_records(rrset)
99
+ # Abort if rrset is something else than an array
100
+ abort('Error: records needs to be array') unless rrset[:records].is_a? Array
101
+
102
+ # Ensure existence of required keys
103
+ rrset[:records].map! do |record|
104
+ # Format the record content
105
+ record = format_single_record(record)
106
+
107
+ # Add disabled from the rrset
108
+ record[:disabled] ||= !!rrset[:disabled]
109
+
110
+ # Return record
111
+ next record unless @version == 0
112
+
113
+ # But add some more for APIv0
114
+ record.merge(name: rrset[:name], type: rrset[:type], ttl: rrset[:ttl])
115
+ end
116
+ rrset
117
+ end
118
+
119
+ # Add records to the ones already existing
120
+ # Only works from API v1 and up
121
+ def add(*rrsets)
122
+ # Get current zone data
123
+ data = get
124
+
125
+ # Return any errors
126
+ return data if data.key?(:error)
127
+
128
+ # Run v0 version
129
+ return add_v0(rrsets, data) if @version == 0
130
+
131
+ # Add these records to the rrset
132
+ rrsets.map! do |rrset|
133
+ # Get current data from rrset
134
+ current = data[:rrsets].select { |r| r[:name] == rrset[:name] && r[:type] == rrset[:type] }
135
+
136
+ # Merge data
137
+ rrset[:records] = current.first[:records] + ensure_array(rrset[:records])
138
+ rrset[:changetype] = 'REPLACE'
139
+ rrset
140
+ end
141
+ modify(rrsets)
142
+ end
143
+
144
+ # Add records to the ones already existing
145
+ # Only works from API v1 and down
146
+ def add_v0(rrsets, data)
147
+ # Add these records to the rrset
148
+ rrsets.map! do |rrset|
149
+ current = data[:records].select do |r|
150
+ r[:name] == rrset[:name] && r[:type] == rrset[:type]
151
+ end
152
+ current.map! do |record|
153
+ {
154
+ content: record[:content],
155
+ disabled: record[:disabled]
156
+ }
157
+ end
158
+ rrset[:records] = current + ensure_array(rrset[:records])
159
+ rrset[:changetype] = 'REPLACE'
160
+ rrset
161
+ end
162
+ modify(rrsets)
163
+ end
164
+
165
+ def update(*rrsets)
166
+ # Set type and format records
167
+ rrsets.map! do |rrset|
168
+ rrset[:changetype] = 'REPLACE'
169
+ rrset[:records] = ensure_array(rrset[:records])
170
+ rrset
171
+ end
172
+ modify(rrsets)
173
+ end
174
+
175
+ def remove(*rrsets)
176
+ # Set type and format records
177
+ rrsets.map! do |rrset|
178
+ rrset[:changetype] = 'DELETE'
179
+ rrset
180
+ end
181
+ apply(rrsets)
182
+ end
183
+ end
184
+ end
data/lib/pdns_api.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'json'
2
+ require 'net/http'
3
+
4
+ # PDNS module
5
+ module PDNS
6
+ require_relative 'pdns_api/client'
7
+
8
+ class << self
9
+ def new(args)
10
+ Client.new(args)
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pdns_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Silke Hofstra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A gem for manipulation of DNS through the PowerDNS API
14
+ email: silke@slxh.eu
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/pdns_api.rb
20
+ - lib/pdns_api/api.rb
21
+ - lib/pdns_api/client.rb
22
+ - lib/pdns_api/config.rb
23
+ - lib/pdns_api/cryptokey.rb
24
+ - lib/pdns_api/http.rb
25
+ - lib/pdns_api/metadata.rb
26
+ - lib/pdns_api/override.rb
27
+ - lib/pdns_api/server.rb
28
+ - lib/pdns_api/version.rb
29
+ - lib/pdns_api/zone.rb
30
+ homepage: https://github.com/silkeh/ruby-pdns_api
31
+ licenses:
32
+ - GPLv3+
33
+ metadata: {}
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 2.4.5.1
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: PowerDNS API gem
54
+ test_files: []