dnsmadeeasy 0.3.2 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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