dnsmadeeasy 0.3.2 → 0.3.5

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.
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'dnsmadeeasy'
@@ -1,37 +1,50 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'dnsmadeeasy/version'
6
6
 
7
- DnsMadeEasy::DESCRIPTION = <<-eof
8
- This is a fully-featured DNS API client for DnsMadeEasy.com, that includes
9
- both the Ruby API and a corresponding CLI interface. This gem is based on the
10
- "dnsmadeeasy-rest-api". We also wish to thank the original author Phil Cohen who
11
- kindly passed on the RubyGems namespace, and now you can install just plain simple
12
- install "dnsmadeeasy" gem. The gem additionally supports storing credentials in the
13
- ~/.dnsmadeeasy/credentials.yml file, supports multiple accounts, encryption, and more.
7
+ # rubocop:todo Naming/HeredocDelimiterCase
8
+ DnsMadeEasy::DESCRIPTION = <<~eof
9
+ This is an authoratative and fully-featured API client for the DNS Provider "DnsMadeEasy.com".
10
+
11
+ This library offers both a rich Ruby API that you can use to automate DNS record management, as well
12
+ as a rich CLI interface with the command line executable "dme" installed when you install the gem.
13
+ The gem additionally supports storing credentials in the ~/.dnsmadeeasy/credentials.yml
14
+ file, supports multiple accounts, encryption, and more.
15
+
16
+ If you are using Chef consider using the "dnsmadeeasy" Chef Cookbook, while uses this gem behind
17
+ the scenes: https://supermarket.chef.io/cookbooks/dnsmadeeasy<br />
18
+
19
+ ACKNOWLEDGEMENTS:
20
+
21
+ 1. This gem is based on the original work contributed by Wanelo.com to the
22
+ now abandonded "dnsmadeeasy-rest-api" client.
23
+
24
+ 2. We also wish to thank the gem author Phil Cohen who
25
+ kindly yielded the "dnsmadeeasy" RubyGems namespace to this gem.
26
+
27
+ 3. We also thank Praneeth Are for contributing the support for secondary domains in 0.3.5.
14
28
  eof
15
29
 
16
30
  Gem::Specification.new do |spec|
17
31
  spec.name = 'dnsmadeeasy'
18
32
  spec.version = DnsMadeEasy::VERSION
19
- spec.authors = ['Konstantin Gredeskoul', 'Arnoud Vermeer', 'Paul Henry', 'James Hart', 'Phil Cohen']
33
+ spec.authors = ['Konstantin Gredeskoul', 'Arnoud Vermeer', 'Paul Henry', 'James Hart', 'Phil Cohen', 'Praneeth Are']
20
34
  spec.email = %w(kigster@gmail.com letuboy@gmail.com hjhart@gmail.com)
21
35
  spec.summary = DnsMadeEasy::DESCRIPTION
22
36
  spec.description = DnsMadeEasy::DESCRIPTION
23
- spec.post_install_message = <<-EOF
24
-
25
- Thank you for using the DnsMadeEasy ruby gem, the Ruby client
26
- API for DnsMadeEasy.com's SDK v2. Please note that this gem
27
- comes with a command line utility 'dme' which you can use
28
- instead of the ruby API if you prefer. Run `dme` with no
29
- arguments to see the help message.
30
-
31
- You can store your credentials in a YAML file in your home
32
- directory. For more information, please see README at:
33
- https://github.com/kigster/dnsmadeeasy
37
+ # rubocop:todo Naming/HeredocDelimiterNaming
38
+ spec.post_install_message = <<~EOF
39
+ Thank you for using the DnsMadeEasy ruby gem, the Ruby client
40
+ API for DnsMadeEasy.com's SDK v2. Please note that this gem
41
+ comes with a rich command line utility 'dme' which you can use
42
+ instead of the ruby API if you prefer. Run `dme` with no
43
+ arguments to see the help message.
34
44
 
45
+ You can also store (multi-account) credentials in a YAML file in
46
+ your home directory. For more information, please see README at:
47
+ https://github.com/kigster/dnsmadeeasy
35
48
  EOF
36
49
 
37
50
  spec.homepage = 'https://github.com/kigster/dnsmadeeasy'
@@ -40,24 +53,25 @@ https://github.com/kigster/dnsmadeeasy
40
53
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
41
54
  f.match(%r{^(test|spec|features)/})
42
55
  end
43
-
56
+
44
57
  spec.bindir = 'exe'
45
58
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
46
59
  spec.require_paths = ['lib']
47
60
 
48
- spec.add_dependency 'sym'
49
- spec.add_dependency 'hashie'
50
- spec.add_dependency 'colored2'
51
61
  spec.add_dependency 'awesome_print'
62
+ spec.add_dependency 'colored2'
63
+ spec.add_dependency 'hashie'
64
+ spec.add_dependency 'sym'
52
65
 
53
- spec.add_development_dependency 'yard'
54
- spec.add_development_dependency 'simplecov'
55
- spec.add_development_dependency 'webmock'
56
66
  spec.add_development_dependency 'bundler'
57
67
  spec.add_development_dependency 'rake'
68
+ spec.add_development_dependency 'relaxed-rubocop'
58
69
  spec.add_development_dependency 'rspec'
59
70
  spec.add_development_dependency 'rspec-its'
60
71
  spec.add_development_dependency 'rubocop'
72
+ spec.add_development_dependency 'simplecov'
73
+ spec.add_development_dependency 'webmock'
74
+ spec.add_development_dependency 'yard'
61
75
 
62
76
  # spec.add_development_dependency 'aruba'
63
77
  end
data/exe/dme CHANGED
@@ -1,8 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'dnsmadeeasy/runner'
4
5
 
5
6
  DnsMadeEasy::Runner.new(ARGV).execute!
6
-
7
-
8
-
data/lib/dme.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'dnsmadeeasy'
2
4
 
3
5
  module DME
@@ -6,12 +8,14 @@ module DME
6
8
  ::DnsMadeEasy::Api::Client.new(key, secret)
7
9
  end
8
10
 
11
+ # rubocop:todo Style/MissingRespondToMissing
12
+ # rubocop:todo Style/MethodMissingSuper
9
13
  def method_missing(method, *args, &block)
10
- begin
11
- DnsMadeEasy.send(method, *args, &block)
12
- rescue NameError => e
13
- puts "Error: #{e.message}"
14
- end
14
+ DnsMadeEasy.send(method, *args, &block)
15
+ rescue NameError => e
16
+ puts "Error: #{e.message}"
15
17
  end
18
+ # rubocop:enable Style/MethodMissingSuper
19
+ # rubocop:enable Style/MissingRespondToMissing
16
20
  end
17
21
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DnsMadeEasy
2
4
  API_BASE_URL_PRODUCTION = 'https://api.dnsmadeeasy.com/V2.0'
3
- API_BASE_URL_SANDBOX = 'https://sandboxapi.dnsmadeeasy.com/V2.0'
5
+ API_BASE_URL_SANDBOX = 'https://api.sandbox.dnsmadeeasy.com/V2.0'
4
6
  end
5
7
 
6
8
  require 'dnsmadeeasy/version'
@@ -22,6 +24,8 @@ module DnsMadeEasy
22
24
  end
23
25
  class NoSuchAccountError < Error;
24
26
  end
27
+ class NoDomainError < Error;
28
+ end
25
29
 
26
30
  class << self
27
31
  attr_accessor :default_api_key,
@@ -36,9 +40,10 @@ module DnsMadeEasy
36
40
  encryption_key = nil)
37
41
 
38
42
  credentials = ::DnsMadeEasy::Credentials.keys_from_file(
39
- file: file || ::DnsMadeEasy::Credentials.default_credentials_path(user: ENV['USER']),
40
- account: account,
41
- encryption_key: encryption_key)
43
+ file: file || ::DnsMadeEasy::Credentials.default_credentials_path(user: ENV['USER']),
44
+ account: account,
45
+ encryption_key: encryption_key
46
+ )
42
47
  if credentials
43
48
  configure do |config|
44
49
  config.api_key = credentials.api_key
@@ -53,8 +58,8 @@ module DnsMadeEasy
53
58
  account: nil,
54
59
  encryption_key: nil)
55
60
 
56
- DnsMadeEasy::Credentials.keys_from_file file: file,
57
- account: account,
61
+ DnsMadeEasy::Credentials.keys_from_file file: file,
62
+ account: account,
58
63
  encryption_key: encryption_key
59
64
  end
60
65
 
@@ -75,17 +80,20 @@ module DnsMadeEasy
75
80
  end
76
81
 
77
82
  def create_client(sandbox = false,
78
- api_key: self.default_api_key,
79
- api_secret: self.default_api_secret,
83
+ api_key: default_api_key,
84
+ api_secret: default_api_secret,
80
85
 
81
86
  **options)
82
87
  raise APIKeyAndSecretMissingError, 'Please set #api_key and #api_secret' unless api_key && api_secret
88
+
83
89
  ::DnsMadeEasy::Api::Client.new(api_key, api_secret, sandbox, **options)
84
90
  end
85
91
 
86
92
  # Basically delegate it all to the Client instance
87
93
  # if the method call is supported.
88
94
  #
95
+ # rubocop:todo Style/MissingRespondToMissing
96
+ # rubocop:todo Style/MethodMissingSuper
89
97
  def method_missing(method, *args, &block)
90
98
  if client.respond_to?(method)
91
99
  client.send(method, *args, &block)
@@ -93,5 +101,7 @@ module DnsMadeEasy
93
101
  super(method, *args, &block)
94
102
  end
95
103
  end
104
+ # rubocop:enable Style/MethodMissingSuper
105
+ # rubocop:enable Style/MissingRespondToMissing
96
106
  end
97
107
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'time'
2
4
  require 'openssl'
3
5
  require 'json'
@@ -9,7 +11,6 @@ require 'dnsmadeeasy/credentials'
9
11
  module DnsMadeEasy
10
12
  module Api
11
13
  class Client
12
-
13
14
  class << self
14
15
  def public_operations
15
16
  (new('a', 'b').methods - Object.methods).map(&:to_s).reject { |r| r =~ /[=]$|^(api_|on_|request)/ }.sort
@@ -22,7 +23,6 @@ module DnsMadeEasy
22
23
  :api_key,
23
24
  :api_secret
24
25
 
25
-
26
26
  def initialize(api_key, api_secret, sandbox = false, options = {})
27
27
  fail 'api_key is undefined' unless api_key
28
28
  fail 'api_secret is undefined' unless api_secret
@@ -36,17 +36,14 @@ module DnsMadeEasy
36
36
  sandbox ? on_sandbox : on_production
37
37
  end
38
38
 
39
-
40
39
  def on_sandbox(&block)
41
40
  with_url(::DnsMadeEasy::API_BASE_URL_SANDBOX, &block)
42
41
  end
43
42
 
44
-
45
43
  def on_production(&block)
46
44
  with_url(::DnsMadeEasy::API_BASE_URL_PRODUCTION, &block)
47
45
  end
48
46
 
49
-
50
47
  # -----------------------------------
51
48
  # ------------- DOMAINS -------------
52
49
  # -----------------------------------
@@ -55,32 +52,26 @@ module DnsMadeEasy
55
52
  get("/dns/managed/id/#{domain_name}")['id']
56
53
  end
57
54
 
58
-
59
55
  def domains
60
56
  get '/dns/managed/'
61
57
  end
62
58
 
63
-
64
59
  def domain(domain_name)
65
60
  get "/dns/managed/#{get_id_by_domain(domain_name)}"
66
61
  end
67
62
 
68
-
69
63
  def delete_domain(domain_name)
70
64
  delete "/dns/managed/#{get_id_by_domain(domain_name)}"
71
65
  end
72
66
 
73
-
74
67
  def create_domains(names)
75
68
  post('/dns/managed/', names: names)
76
69
  end
77
70
 
78
-
79
71
  def create_domain(domain_name)
80
72
  create_domains([domain_name])
81
73
  end
82
74
 
83
-
84
75
  # -----------------------------------
85
76
  # ------------- RECORDS -------------
86
77
  # -----------------------------------
@@ -89,55 +80,49 @@ module DnsMadeEasy
89
80
  get "/dns/managed/#{get_id_by_domain(domain_name)}/records"
90
81
  end
91
82
 
92
-
93
83
  alias all records_for
94
84
 
95
-
96
85
  def find_all(domain_name, name, type)
97
86
  records = records_for(domain_name)
98
87
  return nil unless records
88
+
99
89
  records['data'].select { |r| r['name'] == name && r['type'] == type }
100
90
  end
101
91
 
102
-
103
92
  def find_first(domain_name, name, type)
104
93
  records = records_for(domain_name)
105
94
  return nil unless records
95
+
106
96
  records['data'].detect { |r| r['name'] == name && r['type'] == type }
107
97
  end
108
98
 
109
-
110
99
  def find_record_ids(domain_name, name, type)
111
100
  records = records_for(domain_name)
112
101
  records['data'].select { |r| r['name'] == name && r['type'] == type }.map { |r| r['id'] }
113
102
  end
114
103
 
115
-
116
104
  def delete_record(domain_name, record_id)
117
105
  delete "/dns/managed/#{get_id_by_domain(domain_name)}/records/#{record_id}/"
118
106
  end
119
107
 
120
-
121
108
  def delete_records(domain_name, ids = [])
122
109
  return if ids.empty?
110
+
123
111
  domain_id = get_id_by_domain(domain_name)
124
112
 
125
113
  delete "/dns/managed/#{domain_id}/records?ids=#{ids.join(',')}"
126
114
  end
127
115
 
128
-
129
116
  def delete_all_records(domain_name)
130
117
  domain_id = get_id_by_domain(domain_name)
131
118
  delete "/dns/managed/#{domain_id}/records"
132
119
  end
133
120
 
134
-
135
121
  def create_record(domain_name, name, type, value, options = {})
136
122
  body = { 'name' => name, 'type' => type, 'value' => value, 'ttl' => 3600, 'gtdLocation' => 'DEFAULT' }
137
123
  post "/dns/managed/#{get_id_by_domain(domain_name)}/records/", body.merge(options)
138
124
  end
139
125
 
140
-
141
126
  # Specific record types
142
127
 
143
128
  def create_a_record(domain_name, name, value, options = {})
@@ -145,81 +130,141 @@ module DnsMadeEasy
145
130
  create_record domain_name, name, 'A', value, options
146
131
  end
147
132
 
148
-
149
133
  def create_aaaa_record(domain_name, name, value, options = {})
150
134
  # TODO: match IPv6 for value
151
135
  create_record domain_name, name, 'AAAA', value, options
152
136
  end
153
137
 
154
-
155
138
  def create_ptr_record(domain_name, name, value, options = {})
156
139
  # TODO: match PTR value
157
140
  create_record domain_name, name, 'PTR', value, options
158
141
  end
159
142
 
160
-
161
143
  def create_txt_record(domain_name, name, value, options = {})
162
144
  # TODO: match TXT value
163
145
  create_record domain_name, name, 'TXT', value, options
164
146
  end
165
147
 
166
-
167
148
  def create_cname_record(domain_name, name, value, options = {})
168
149
  # TODO: match CNAME value
169
150
  create_record domain_name, name, 'CNAME', value, options
170
151
  end
171
152
 
172
-
173
153
  def create_ns_record(domain_name, name, value, options = {})
174
154
  # TODO: match domainname for value
175
155
  create_record domain_name, name, 'NS', value, options
176
156
  end
177
157
 
178
-
179
158
  def create_spf_record(domain_name, name, value, options = {})
180
159
  create_record domain_name, name, 'SPF', value, options
181
160
  end
182
161
 
183
-
184
162
  def create_mx_record(domain_name, name, priority, value, options = {})
185
163
  options.merge!('mxLevel' => priority)
186
164
 
187
165
  create_record domain_name, name, 'MX', value, options
188
166
  end
189
167
 
190
-
191
168
  def create_srv_record(domain_name, name, priority, weight, port, value, options = {})
192
169
  options.merge!('priority' => priority, 'weight' => weight, 'port' => port)
193
170
  create_record domain_name, name, 'SRV', value, options
194
171
  end
195
172
 
196
-
173
+ # rubocop:todo Naming/MethodParameterName
174
+ # rubocop:todo Naming/VariableName
197
175
  def create_httpred_record(domain_name, name, value, redirectType = 'STANDARD - 302', description = '', keywords = '', title = '', options = {})
176
+ # rubocop:enable Naming/VariableName
177
+ # rubocop:todo Naming/VariableName
198
178
  options.merge!('redirectType' => redirectType, 'description' => description, 'keywords' => keywords, 'title' => title)
179
+ # rubocop:enable Naming/VariableName
199
180
  create_record domain_name, name, 'HTTPRED', value, options
200
181
  end
201
-
182
+ # rubocop:enable Naming/MethodParameterName
202
183
 
203
184
  def update_record(domain, record_id, name, type, value, options = {})
204
185
  body = { 'name' => name, 'type' => type, 'value' => value, 'ttl' => 3600, 'gtdLocation' => 'DEFAULT', 'id' => record_id }
205
186
  put "/dns/managed/#{get_id_by_domain(domain)}/records/#{record_id}/", body.merge(options)
206
187
  end
207
188
 
208
-
209
189
  def update_records(domain, records, options = {})
210
190
  body = records.map do |record|
211
191
  {
212
- 'id' => record['id'],
213
- 'name' => record['name'],
214
- 'type' => record['type'],
215
- 'value' => record['value'],
192
+ 'id' => record['id'],
193
+ 'name' => record['name'],
194
+ 'type' => record['type'],
195
+ 'value' => record['value'],
216
196
  'gtdLocation' => record['gtdLocation'],
217
- 'ttl' => record['ttl']
197
+ 'ttl' => record['ttl']
218
198
  }.merge(options)
219
199
  end
220
200
  put "/dns/managed/#{get_id_by_domain(domain)}/records/updateMulti/", body
221
201
  end
222
202
 
203
+ # -----------------------------------
204
+ # ------- Secondary Domains ---------
205
+ # -----------------------------------
206
+
207
+ def secondary_domains
208
+ get '/dns/secondary'
209
+ end
210
+
211
+ def secondary_domain(domain_id)
212
+ get "/dns/secondary/#{domain_id}"
213
+ end
214
+
215
+ def create_secondary_domains(domain_names, ip_set_id)
216
+ body = { names: domain_names, ipSetId: ip_set_id }
217
+ post '/dns/secondary', body
218
+ end
219
+
220
+ def create_secondary_domain(domain_name, ip_set_id)
221
+ domains = [domain_name]
222
+ create_secondary_domains(domains, ip_set_id)
223
+ end
224
+
225
+ def update_secondary_domains(domain_ids, ip_set_id)
226
+ body = { ids: domain_ids, ipSetId: ip_set_id }
227
+ put '/dns/secondary', body
228
+ end
229
+
230
+ def get_id_by_secondary_domain(domain_name)
231
+ domain_data = secondary_domains['data'].find do |domain|
232
+ domain['name'] == domain_name
233
+ end
234
+ raise NoDomainError, "#{domain_name} does not exist" unless domain_data
235
+
236
+ domain_data['id']
237
+ end
238
+
239
+ def delete_secondary_domain(domain_name)
240
+ delete "/dns/secondary/#{get_id_by_secondary_domain(domain_name)}"
241
+ end
242
+
243
+ # -----------------------------------
244
+ # ------- Secondary IpSet -----------
245
+ # -----------------------------------
246
+
247
+ def secondary_ip_sets
248
+ get '/dns/secondary/ipSet'
249
+ end
250
+
251
+ def secondary_ip_set(ip_set_id)
252
+ get "/dns/secondary/ipSet/#{ip_set_id}"
253
+ end
254
+
255
+ def create_secondary_ip_set(name, ips)
256
+ body = { name: name, ips: ips }
257
+ post '/dns/secondary/ipSet', body
258
+ end
259
+
260
+ def update_secondary_ip_set(ip_set_id, name, ips)
261
+ body = { name: name, id: ip_set_id, ips: ips }
262
+ put "/dns/secondary/ipSet/#{ip_set_id}", body
263
+ end
264
+
265
+ def delete_secondary_ip_set(ip_set_id)
266
+ delete "/dns/secondary/ipSet/#{ip_set_id}"
267
+ end
223
268
 
224
269
  private
225
270
 
@@ -229,7 +274,6 @@ module DnsMadeEasy
229
274
  end
230
275
  end
231
276
 
232
-
233
277
  def delete(path, body = nil)
234
278
  request(path) do |uri|
235
279
  req = Net::HTTP::Delete.new(uri)
@@ -238,7 +282,6 @@ module DnsMadeEasy
238
282
  end
239
283
  end
240
284
 
241
-
242
285
  def put(path, body = nil)
243
286
  request(path) do |uri|
244
287
  req = Net::HTTP::Put.new(uri)
@@ -247,7 +290,6 @@ module DnsMadeEasy
247
290
  end
248
291
  end
249
292
 
250
-
251
293
  def post(path, body)
252
294
  request(path) do |uri|
253
295
  req = Net::HTTP::Post.new(uri)
@@ -256,7 +298,6 @@ module DnsMadeEasy
256
298
  end
257
299
  end
258
300
 
259
-
260
301
  def request(path)
261
302
  uri = URI("#{base_uri}#{path}")
262
303
 
@@ -275,7 +316,6 @@ module DnsMadeEasy
275
316
  process_response!(http.request(request))
276
317
  end
277
318
 
278
-
279
319
  def process_response!(response)
280
320
  response.value # raise Net::HTTPServerException unless response was 2xx
281
321
  process_rate_limits(response)
@@ -283,13 +323,12 @@ module DnsMadeEasy
283
323
  Hashie::Mash.new(JSON.parse(unparsed_json))
284
324
  rescue Net::HTTPServerException => e
285
325
  if e.message =~ /403.*forbidden/i
286
- raise ::DnsMadeEasy::AuthenticationError.new(e)
326
+ raise ::DnsMadeEasy::AuthenticationError, e
287
327
  else
288
328
  raise e
289
329
  end
290
330
  end
291
331
 
292
-
293
332
  def process_rate_limits(response)
294
333
  response.each_header do |header, value|
295
334
  @requests_remaining = value.to_i if header == 'x-dnsme-requestsremaining'
@@ -297,21 +336,19 @@ module DnsMadeEasy
297
336
  end
298
337
  end
299
338
 
300
-
301
339
  def request_headers
302
340
  request_date = Time.now.httpdate
303
341
  hmac = OpenSSL::HMAC.hexdigest('sha1', @api_secret, request_date)
304
342
  {
305
- 'Accept' => 'application/json',
306
- 'x-dnsme-apiKey' => @api_key,
343
+ 'Accept' => 'application/json',
344
+ 'x-dnsme-apiKey' => @api_key,
307
345
  'x-dnsme-requestDate' => request_date,
308
- 'x-dnsme-hmac' => hmac
346
+ 'x-dnsme-hmac' => hmac
309
347
  }
310
348
  end
311
349
 
312
-
313
350
  def with_url(url)
314
- old_value = self.base_uri
351
+ old_value = base_uri
315
352
  self.base_uri = url
316
353
  if block_given?
317
354
  yield