pdns_api 0.0.4

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.
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: []