dnsmadeeasy-api 0.9 → 0.9.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.
@@ -12,8 +12,8 @@ Ruby client for DNSMadeEasy API.
12
12
  require "rubygems"
13
13
  require "dnsmadeeasy/api"
14
14
 
15
- api_key = <your dnsmadeeasy api key>
16
- secret_ket = <your dnsmadeeasy secret key>
15
+ api_key = "your-12345-api-67890-key"
16
+ secret_key = "your-12345-secret-67890-key"
17
17
  api = DnsMadeEasy::Api(api_key, secret_key)
18
18
  api.list_records "sigfig.com"
19
19
 
@@ -23,6 +23,12 @@ This is a great way to test your application without changing your production DN
23
23
  api = DnsMadeEasy::Api(api_key, secret_key, true)
24
24
  api.list_records "sigfig.com"
25
25
 
26
+ The api calls throw the following exceptions:
27
+ * BadRequestError: For cases when there is missing information or the api limits have been exceeded
28
+ * ResourceNotFoundError: For cases when a request is made for an unknown domain or record
29
+ * AuthorizationFailedError: For cases when the request cannot be authorized
30
+ * InvalidRecordError: When a record to be created or updated is not well formed
31
+
26
32
  == Command line tool
27
33
 
28
34
  The client comes with a command line tool "dme". Use "dme --help" to see how to use the command.
@@ -33,5 +39,5 @@ The command line tool requires that your api credentials be stored in /etc/dnsma
33
39
  The command line tool also allows the running of queries in the sandbox mode. To do so, create
34
40
  /etc/dnsmadeeasy/api_sandbox.keys with your sandbox api key and secret key and use the --sandbox option
35
41
  with every command.
36
-
37
- =end
42
+
43
+ =end
data/Rakefile CHANGED
@@ -2,12 +2,12 @@ require "rubygems"
2
2
  require "rake"
3
3
  require "echoe"
4
4
 
5
- Echoe.new("dnsmadeeasy-api", "0.9") do |p|
5
+ Echoe.new("dnsmadeeasy-api", "0.9.5") do |p|
6
6
  p.description = "Ruby client for DNSMadeEasy API."
7
7
  p.summary = "Ruby client for DNSMadeEasy API."
8
8
  p.url = "http://rubygems.org/gems/dnsmadeeasy-api"
9
9
  p.author = "Nitesh Goel"
10
- p.email = "nitesh@wikinvest.com"
10
+ p.email = "nitesh@sigfig.com"
11
11
  p.ignore_pattern = ["tmp/*", "script/*"]
12
12
  p.install_message = "Create /etc/dnsmadeeasy/api.keys and/or /etc/dnsmadeeasy/api_sandbox.keys with the following information\napi_key=<your api key>\nsecret_key=<your secret key>\nto use the dme binary."
13
13
  p.runtime_dependencies = ["rest-client", "json"]
data/bin/dme CHANGED
@@ -27,6 +27,7 @@ module DnsMadeEasy
27
27
  "describe-domain" => "Describe a domain entry",
28
28
  "list-records" => "List records for a domain",
29
29
  "create-record" => "Create a new dns record",
30
+ "delete-records" => "Delete multiple dns records",
30
31
  "delete-record" => "Delete a dns record",
31
32
  "update-record" => "Update an existing dns record",
32
33
  "describe-record" => "Describe an existing dns record"
@@ -56,9 +57,7 @@ module DnsMadeEasy
56
57
 
57
58
  def show_response(response)
58
59
  if @json
59
- if response.is_a?(TrueClass) || response.is_a?(FalseClass)
60
- response = { :success => response }
61
- end
60
+ response = { :data => response }
62
61
  puts response.to_json
63
62
  elsif response.is_a?(TrueClass) || response.is_a?(FalseClass)
64
63
  if response
@@ -70,7 +69,7 @@ module DnsMadeEasy
70
69
  response.each do |x|
71
70
  puts x
72
71
  end
73
- else
72
+ elsif !response.empty?
74
73
  table_fields = {}
75
74
  response = [response] if response.instance_of?(Hash)
76
75
  response.each do |x|
@@ -184,7 +183,9 @@ begin
184
183
  when "list-domains"
185
184
  printer.show_response api.list_domains
186
185
  when "delete-domains"
187
- unless force
186
+ if force
187
+ printer.show_response api.delete_domains!
188
+ else
188
189
  puts "The following domains are listed in your account:"
189
190
  printer.show_response api.list_domains
190
191
  puts "Are you sure you want to delete all domains? (yes/no)"
@@ -192,21 +193,25 @@ begin
192
193
  unless response.downcase == "yes"
193
194
  printer.say_bye "Domains not deleted"
194
195
  end
196
+ api.delete_domains!
197
+ puts "Done"
195
198
  end
196
- printer.show_response api.delete_domains!
197
199
  when "create-domain"
198
200
  printer.show_error "Please specify a domain name" if domain.nil?
199
201
  printer.show_response api.create_domain!(domain)
200
202
  when "delete-domain"
201
203
  printer.show_error "Please specify a domain name" if domain.nil?
202
- unless force
204
+ if force
205
+ printer.show_response api.delete_domain!(domain)
206
+ else
203
207
  puts "Are you sure you want to delete #{domain}? (yes/no)"
204
208
  response = STDIN.gets.chomp.downcase
205
209
  unless response.downcase == "yes"
206
210
  printer.say_bye "Domain #{domain} not deleted"
207
211
  end
212
+ api.delete_domain!(domain)
213
+ puts "Done"
208
214
  end
209
- printer.show_response api.delete_domain!(domain)
210
215
  when "describe-domain"
211
216
  printer.show_error "Please specify a domain name" if domain.nil?
212
217
  printer.show_response api.describe_domain(domain)
@@ -219,23 +224,39 @@ begin
219
224
  when "delete-record"
220
225
  printer.show_error "Please specify a domain name" if domain.nil?
221
226
  printer.show_response api.describe_record(domain, record_id)
222
- unless force
227
+ if force
228
+ printer.show_response api.delete_record!(domain, record_id)
229
+ else
223
230
  puts "Are you sure you want to delete this record? (yes/no)"
224
231
  response = STDIN.gets.chomp.downcase
225
232
  unless response.downcase == "yes"
226
233
  printer.say_bye "Record not deleted"
227
234
  end
235
+ api.delete_record!(domain, record_id)
236
+ puts "Done"
228
237
  end
229
- printer.show_response api.delete_record!(domain, record_id)
230
238
  when "update-record"
231
239
  printer.show_error "Please specify a domain name" if domain.nil?
232
240
  printer.show_response api.update_record!(domain, record_id, options)
233
241
  when "describe-record"
234
242
  printer.show_error "Please specify a domain name" if domain.nil?
235
243
  printer.show_response api.describe_record(domain, record_id)
244
+ when "delete-records"
245
+ printer.show_error "Please specify a domain name" if domain.nil?
246
+ printer.show_response api.list_records(domain, options)
247
+ if force
248
+ printer.show_response api.delete_records!(domain, options)
249
+ else
250
+ puts "Are you sure you want to delete these records? (yes/no)"
251
+ response = STDIN.gets.chomp.downcase
252
+ unless response.downcase == "yes"
253
+ printer.say_bye "Records not deleted"
254
+ end
255
+ api.delete_records!(domain, options)
256
+ puts "Done"
257
+ end
236
258
  when "help"
237
259
  help_for_command = ARGV.shift
238
-
239
260
  else
240
261
  printer.show_error "Please enter a valid command"
241
262
  end
@@ -2,13 +2,13 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{dnsmadeeasy-api}
5
- s.version = "0.9"
5
+ s.version = "0.9.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = [%q{Nitesh Goel}]
9
- s.date = %q{2011-07-06}
9
+ s.date = %q{2011-07-07}
10
10
  s.description = %q{Ruby client for DNSMadeEasy API.}
11
- s.email = %q{nitesh@wikinvest.com}
11
+ s.email = %q{nitesh@sigfig.com}
12
12
  s.executables = [%q{dme}]
13
13
  s.extra_rdoc_files = [%q{README.rdoc}, %q{bin/dme}, %q{lib/dnsmadeeasy/api.rb}, %q{lib/dnsmadeeasy/exceptions.rb}]
14
14
  s.files = [%q{Manifest}, %q{README.rdoc}, %q{Rakefile}, %q{bin/dme}, %q{lib/dnsmadeeasy/api.rb}, %q{lib/dnsmadeeasy/exceptions.rb}, %q{dnsmadeeasy-api.gemspec}]
@@ -19,8 +19,8 @@ Ruby client for DNSMadeEasy API.
19
19
  require "rubygems"
20
20
  require "dnsmadeeasy/api"
21
21
 
22
- api_key = <your dnsmadeeasy api key>
23
- secret_ket = <your dnsmadeeasy secret key>
22
+ api_key = "your-12345-api-67890-key"
23
+ secret_key = "your-12345-secret-67890-key"
24
24
  api = DnsMadeEasy::Api(api_key, secret_key)
25
25
  api.list_records "sigfig.com"
26
26
 
@@ -30,6 +30,12 @@ This is a great way to test your application without changing your production DN
30
30
  api = DnsMadeEasy::Api(api_key, secret_key, true)
31
31
  api.list_records "sigfig.com"
32
32
 
33
+ The api calls throw the following exceptions:
34
+ * BadRequestError: For cases when there is missing information or the api limits have been exceeded
35
+ * ResourceNotFoundError: For cases when a request is made for an unknown domain or record
36
+ * AuthorizationFailedError: For cases when the request cannot be authorized
37
+ * InvalidRecordError: When a record to be created or updated is not well formed
38
+
33
39
  == Command line tool
34
40
 
35
41
  The client comes with a command line tool "dme". Use "dme --help" to see how to use the command.
@@ -40,7 +46,7 @@ The command line tool requires that your api credentials be stored in /etc/dnsma
40
46
  The command line tool also allows the running of queries in the sandbox mode. To do so, create
41
47
  /etc/dnsmadeeasy/api_sandbox.keys with your sandbox api key and secret key and use the --sandbox option
42
48
  with every command.
43
-
49
+
44
50
  =end
45
51
 
46
52
  module DnsMadeEasy
@@ -60,169 +66,224 @@ module DnsMadeEasy
60
66
  end
61
67
 
62
68
  # List all domains in the account.
63
- # Returns an array of domain names in the account.
64
- # Throws DnsMadeEasy::AuthorizationFailedError
69
+ #
70
+ # Returns an array of domain names in the account, e.g.
71
+ # ["sigfig.com", "wikinvest.com"]
65
72
  def list_domains
66
- begin
73
+ execute_with_caution do
67
74
  response = RestClient.get request_url, headers
68
75
  response_hash = JSON.parse(response)
69
76
  return response_hash.has_key?("list") ? response_hash["list"] : []
70
- rescue RestClient::Forbidden => e
71
- raise DnsMadeEasy::AuthorizationFailedError
72
77
  end
73
78
  end
74
79
 
75
80
  # Delete all domains in the account.
76
- # Returns true or throws an exception.
77
- # Throws DnsMadeEasy::AuthorizationFailedError
81
+ #
82
+ # Returns an array of domains deleted, e.g.
83
+ # ["sigfig.com", "wikinvest.com"]
78
84
  def delete_domains!
79
- begin
85
+ execute_with_caution do
86
+ domains = list_domains
80
87
  response = RestClient.delete request_url, headers
81
- return true
82
- rescue RestClient::Forbidden => e
83
- raise DnsMadeEasy::AuthorizationFailedError
88
+ return domains
84
89
  end
85
90
  end
86
91
 
87
92
  # Create a new domain entry.
88
- # Returns a hash of the newly created domain entry.
89
- # Throws DnsMadeEasy::InvalidDomainNameError, DnsMadeEasy::DuplicateDomainError, or DnsMadeEasy::AuthorizationFailedError
93
+
94
+ # Returns a hash of the newly created domain entry, e.g.
95
+ # { "name" => "sigfig.com", "nameServer" => ["ns66.dnsmadeeasy.com", "ns99.dnsmadeeasy.com"], "gtdEnabled" => true }
90
96
  def create_domain!(domain)
91
- begin
97
+ execute_with_caution :domain => domain do
92
98
  response = RestClient.put request_url(:path => "#{domain}"), {}, headers
93
99
  return JSON.parse(response)
94
- rescue RestClient::BadRequest => e
95
- error = JSON.parse(e.http_body)
96
- if error["error"][0] == "Invalid domain name."
97
- raise DnsMadeEasy::InvalidDomainNameError, domain
98
- else
99
- raise DnsMadeEasy::DuplicateDomainError, domain
100
- end
101
- rescue RestClient::Forbidden => e
102
- raise DnsMadeEasy::AuthorizationFailedError
103
100
  end
104
101
  end
105
102
 
106
103
  # Delete a domain entry.
107
- # Returns true or throws an exception.
108
- # Throws DnsMadeEasy::UnknownDomainError, DnsMadeEasy::RequestFailedError, or DnsMadeEasy::AuthorizationFailedError
104
+
105
+ # Returns a hash of the deleted domain entry, e.g.
106
+ # { "name" => "sigfig.com", "nameServer" => ["ns66.dnsmadeeasy.com", "ns99.dnsmadeeasy.com"], "gtdEnabled" => true }
109
107
  def delete_domain!(domain)
110
- begin
108
+ execute_with_caution :domain => domain do
109
+ description = describe_domain(domain)
111
110
  response = RestClient.delete request_url(:path => "#{domain}"), headers
112
- return true
113
- rescue RestClient::ResourceNotFound => e
114
- raise DnsMadeEasy::UnknownDomainError, domain
115
- rescue RestClient::BadRequest => e
116
- error = JSON.parse(e.http_body)
117
- raise DnsMadeEasy::RequestFailedError, error["error"][0]
118
- rescue RestClient::Forbidden => e
119
- raise DnsMadeEasy::AuthorizationFailedError
111
+ return description
120
112
  end
121
113
  end
122
114
 
123
115
  # Describe a domain entry.
124
- # Returns a hash of the domain entry.
125
- # Throws DnsMadeEasy::UnknownDomainError or DnsMadeEasy::AuthorizationFailedError
116
+
117
+ # Returns a hash of the domain entry, e.g.
118
+ # { "name" => "sigfig.com", "nameServer" => ["ns66.dnsmadeeasy.com", "ns99.dnsmadeeasy.com"], "gtdEnabled" => true }
126
119
  def describe_domain(domain)
127
- begin
120
+ execute_with_caution :domain => domain do
128
121
  response = RestClient.get request_url(:path => "#{domain}"), headers
129
122
  return JSON.parse(response)
130
- rescue RestClient::ResourceNotFound => e
131
- raise DnsMadeEasy::UnknownDomainError, domain
132
- rescue RestClient::Forbidden => e
133
- raise DnsMadeEasy::AuthorizationFailedError
134
123
  end
135
124
  end
136
125
 
137
126
  # List records for a domain.
138
- # Returns an array of hashes, each hash representing a dns entry.
139
- # Throws DnsMadeEasy::UnknownDomainError or DnsMadeEasy::AuthorizationFailedError
127
+ #
128
+ # The filter parameter allows you to list a list a subset of records filtered by a criteria. Available filters:
129
+ # * { :name => "www" }: Lists all entries for host "www"
130
+ # * { :type => :A }: Lists all A records
131
+ # * { :gtdLocation => :EUROPE } List all entries for EUROPE Traffic Director
132
+ #
133
+ # Returns an array of hashes, each hash representing a dns entry, e.g.
134
+ # [
135
+ # { "name" => "", "type" => "A", "data" => "127.0.0.1", "ttl" => 7200, "id" => 12345, "gtdLocation" => "DEFAULT" }
136
+ # { "name" => "www", "type" => "CNAME", data => "sigfig.com.", "ttl" => 7200, id => 23456, "gtdLocation" => "DEFAULT" }
137
+ # ]
140
138
  def list_records(domain, filter={})
141
- begin
139
+ execute_with_caution :domain => domain do
142
140
  response = RestClient.get request_url(:path => "#{domain}/records", :query => filter), headers
143
141
  return JSON.parse(response)
144
- rescue RestClient::ResourceNotFound => e
145
- raise DnsMadeEasy::UnknownDomainError, domain
146
- rescue RestClient::Forbidden => e
147
- raise DnsMadeEasy::AuthorizationFailedError
148
142
  end
149
143
  end
150
144
 
151
- # Create a new dns record
152
- # record should be a hash with the following values:
145
+ # Create a new dns record.
146
+ #
147
+ # Record should be a hash with the following values:
153
148
  #
154
- # :name => hostname, e.g. www
155
- # :type => e.g. :A, :CNAME, :MX, :TXT, :SRV, :NS, :AAAA, :HTTPRED, :PTR
156
- # :data => publicname, e.g. "66.88.99.44" or "ec2-gibberish.amazonaws.com"
157
- # :gtdLocation => "DEFAULT", (optional, defaults to DEFAULT)
158
- # :ttl => time to live, e.g. 300
149
+ # :name => Hostname. E.g. www, or empty string for root domain
150
+ # :type => Record type. E.g. :A, :CNAME, :MX, :TXT, :SRV, :NS, :AAAA, :HTTPRED, :PTR
151
+ # :data => Public name. E.g. "66.88.99.44" or "ec2-gibberish.amazonaws.com."
152
+ # :gtdLocation => Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE (optional, defaults to DEFAULT)
153
+ # :ttl => Time to live. The amount of time a record will be cached before being refreshed. E.g. 300
159
154
  #
160
- # for :CNAME record type, the domain name is automatically added to the entry unless
161
- # the :data field ends in a .
162
- # e.g., for domain sigfig.com,
163
- # :data => "blog.google.com" for a cname entry resolves to blog.google.com.sigfig.com
164
- # but :data => "blog.google.com." resolves to blog.google.com.
155
+ # Here's a list of possible data values, with the record type they are used with:
156
+ # * A: <host IP>
157
+ # * AAAA: <IPv6 host IP>
158
+ # * CNAME: <target name>
159
+ # * HTTPRED: <redirection URL>
160
+ # * MX: <priority> <target name>
161
+ # * NS: <name server>
162
+ # * PTR: <target name>
163
+ # * SRV: <priority> <weight> <port> <target name>
164
+ # * TXT: <text value>
165
165
  #
166
- # Returns a hash of the newly created dns entry.
167
- # Throws DnsMadeEasy::InvalidRecordError, DnsMadeEasy::UnknownDomainError, or DnsMadeEasy::AuthorizationFailedError
166
+ # N.B. for CNAME, MX, NS, PTR, and SRV records, the domain name of the dns record is automatically
167
+ # appended to the given data unless the data ends with a "." So, to map, say mail to mail.google.com,
168
+ # use "mail.google.com." as the data value. By the same logic, to map "www.sigfig.com" to, say, "server1.sigfig.com",
169
+ # just use "server1" as the data value or "server1.sigfig.com."; don't give "server1.sigfig.com" because that'll
170
+ # essentially resolve to server1.sigfig.com.sigfig.com.
171
+ #
172
+ # Returns a hash of the newly created dns entry, e.g.
173
+ # { "name" => "www", "type" => "CNAME", data => "sigfig.com.", "ttl" => 7200, id => 23456, "gtdLocation" => "DEFAULT" }
168
174
  def create_record!(domain, record)
169
175
  validate_record(record)
170
176
  request_data = {
171
177
  :gtdLocation => "DEFAULT"
172
178
  }.merge(record)
173
- begin
179
+ execute_with_caution :domain => domain do
174
180
  response = RestClient.post request_url(:path => "#{domain}/records"), request_data.to_json, headers(:content_type => "application/json")
175
181
  return JSON.parse(response)
176
- rescue RestClient::BadRequest => e
177
- raise DnsMadeEasy::InvalidRecordError, e.http_body
178
- rescue RestClient::ResourceNotFound => e
179
- raise DnsMadeEasy::UnknownDomainError, domain
180
- rescue RestClient::Forbidden => e
181
- raise DnsMadeEasy::AuthorizationFailedError
182
182
  end
183
183
  end
184
184
 
185
185
  # Delete a dns record.
186
- # Returns true or throws an exception.
187
- # Throws DnsMadeEasy::UnknownRecordError, or DnsMadeEasy::AuthorizationFailedError
186
+ #
187
+ # Returns a hash of the deleted dns entry, e.g.
188
+ # { "name" => "", "type" => "A", "data" => "127.0.0.1", "ttl" => 7200, "id" => 12345, "gtdLocation" => "DEFAULT" }
188
189
  def delete_record!(domain, record_id)
189
- begin
190
+ execute_with_caution :domain => domain, :record => record_id do
191
+ record = describe_record(domain, record_id)
190
192
  response = RestClient.delete request_url(:path => "#{domain}/records/#{record_id}"), headers
191
- return true
192
- rescue RestClient::ResourceNotFound => e
193
- raise DnsMadeEasy::UnknownRecordError.new(domain, record_id)
194
- rescue RestClient::Forbidden => e
195
- raise DnsMadeEasy::AuthorizationFailedError
193
+ return record
194
+ end
195
+ end
196
+
197
+ # Delete multiple records for a domain.
198
+ #
199
+ # The filter parameter allows you to list a list a subset of records filtered by a criteria. Available filters:
200
+ # * { :name => "www" }: Lists all entries for host "www"
201
+ # * { :type => :A }: Lists all A records
202
+ # * { :gtdLocation => :EUROPE } List all entries for EUROPE Traffic Director
203
+ #
204
+ # N.B. Given that there are limits to the number of api requests, the amoticity of this action is not guaranteed.
205
+ # This means that it is possible under certain circumstances that not all records that match the given criteria
206
+ # will be deleted.
207
+ #
208
+ # Returns an array of hashes, each hash representing a deleted dns entry, e.g.
209
+ # [
210
+ # { "name" => "", "type" => "A", "data" => "127.0.0.1", "ttl" => 7200, "id" => 12345, "gtdLocation" => "DEFAULT" }
211
+ # { "name" => "www", "type" => "CNAME", data => "sigfig.com.", "ttl" => 7200, id => 23456, "gtdLocation" => "DEFAULT" }
212
+ # ]
213
+ # An empty array is returned if no deletions are made.
214
+ def delete_records!(domain, filter={})
215
+ record_list = list_records(domain, filter)
216
+ unless record_list.empty?
217
+ if record_list.size == 1
218
+ delete_record!(domain, record_list[0]["id"])
219
+ elsif requests_remaining >= record_list.size
220
+ record_list.each do |record|
221
+ delete_record!(domain, record["id"])
222
+ end
223
+ else
224
+ raise DnsMadeEasy::BadRequestError, "Not enough requests remaining to complete the operation"
225
+ end
196
226
  end
227
+ return record_list
197
228
  end
198
229
 
199
- # Update an existing dns record
200
- # Returns the latest hash of the dns entry.
201
- # Throws DnsMadeEasy::InvalidRecordError, DnsMadeEasy::UnknownRecordError, or DnsMadeEasy::AuthorizationFailedError
230
+ # Update an existing dns record.
231
+ #
232
+ # Record should be a hash with the following values:
233
+ #
234
+ # :name => Hostname. E.g. www, or empty string for root domain
235
+ # :type => Record type. E.g. :A, :CNAME, :MX, :TXT, :SRV, :NS, :AAAA, :HTTPRED, :PTR
236
+ # :data => Public name. E.g. "66.88.99.44" or "ec2-gibberish.amazonaws.com."
237
+ # :gtdLocation => Global Traffic Director location. Values: DEFAULT, US_EAST, US_WEST, EUROPE (optional, defaults to DEFAULT)
238
+ # :ttl => Time to live. The amount of time a record will be cached before being refreshed. E.g. 300
239
+ #
240
+ # Here's a list of possible data values, with the record type they are used with:
241
+ # * A: <host IP>
242
+ # * AAAA: <IPv6 host IP>
243
+ # * CNAME: <target name>
244
+ # * HTTPRED: <redirection URL>
245
+ # * MX: <priority> <target name>
246
+ # * NS: <name server>
247
+ # * PTR: <target name>
248
+ # * SRV: <priority> <weight> <port> <target name>
249
+ # * TXT: <text value>
250
+ #
251
+ # N.B. for CNAME, MX, NS, PTR, and SRV records, the domain name of the dns record is automatically
252
+ # appended to the given data unless the data ends with a "." So, to map, say mail to mail.google.com,
253
+ # use "mail.google.com." as the data value. By the same logic, to map "www.sigfig.com" to, say, "server1.sigfig.com",
254
+ # just use "server1" as the data value or "server1.sigfig.com."; don't give "server1.sigfig.com" because that'll
255
+ # essentially resolve to server1.sigfig.com.sigfig.com.
256
+ #
257
+ # Returns a hash of the newly updated dns entry, e.g.
258
+ # { "name" => "www", "type" => "CNAME", data => "sigfig.com.", "ttl" => 7200, id => 23456, "gtdLocation" => "DEFAULT" }
202
259
  def update_record!(domain, record_id, record)
203
- begin
260
+ validate_record(record)
261
+ execute_with_caution :domain => domain, :record => record_id do
204
262
  response = RestClient.put request_url(:path => "#{domain}/records/#{record_id}"), record.to_json, headers(:content_type => "application/json")
205
263
  return describe_record(domain, record_id)
206
- rescue RestClient::BadRequest => e
207
- raise DnsMadeEasy::InvalidRecordError, e.http_body
208
- rescue RestClient::ResourceNotFound => e
209
- raise DnsMadeEasy::UnknownRecordError.new(domain, record_id)
210
- rescue RestClient::Forbidden => e
211
- raise DnsMadeEasy::AuthorizationFailedError
212
264
  end
213
265
  end
214
266
 
215
267
  # Describe an existing dns record.
268
+ #
216
269
  # Returns a hash of the dns entry.
217
- # Throws DnsMadeEasy::UnknownRecordError, or DnsMadeEasy::AuthorizationFailedError
270
+ # { "name" => "www", "type" => "CNAME", data => "sigfig.com.", "ttl" => 7200, id => 23456, "gtdLocation" => "DEFAULT" }
218
271
  def describe_record(domain, record_id)
219
- begin
272
+ execute_with_caution :domain => domain, :record => record_id do
220
273
  response = RestClient.get request_url(:path => "#{domain}/records/#{record_id}"), headers
221
274
  return JSON.parse(response)
222
- rescue RestClient::ResourceNotFound => e
223
- raise DnsMadeEasy::UnknownRecordError.new(domain, record_id)
224
- rescue RestClient::Forbidden => e
225
- raise DnsMadeEasy::AuthorizationFailedError
275
+ end
276
+ end
277
+
278
+ # Return the umber of api requests remaining.
279
+ def requests_remaining
280
+ begin
281
+ execute_with_caution do
282
+ response = RestClient.get request_url, headers
283
+ return response.headers[:x_dnsme_requestsremaining].to_i if response.headers.has_key?(:x_dnsme_requestsremaining)
284
+ end
285
+ rescue DnsMadeEasy::BadRequestError => e
286
+ return 0
226
287
  end
227
288
  end
228
289
 
@@ -238,8 +299,14 @@ module DnsMadeEasy
238
299
 
239
300
  # check record types
240
301
  acceptable_types = [:A, :CNAME, :MX, :TXT, :SRV, :NS, :AAAA, :HTTPRED, :PTR]
241
- raise DnsMadeEasy::InvalidRecordError, "Invalid record type #{record[:type]}" unless acceptable_types.include?(record[:type])
302
+ raise DnsMadeEasy::InvalidRecordError, "Invalid record type #{record[:type]}" unless acceptable_types.include?(record[:type].to_sym)
242
303
 
304
+ # check gtd location
305
+ acceptable_location = [:DEFAULT, :US_EAST, :US_WEST, :EUROPE]
306
+ if record.has_key?(:gtdLocation) && acceptable_location.include?(record[:gtdLocation].to_sym)
307
+ raise DnsMadeEasy::InvalidRecordError, "Invalid gtd location #{record[:gtdLocation]}"
308
+ end
309
+
243
310
  # check non empty fields
244
311
  non_empty_fields = [:ttl, :data]
245
312
  non_empty_fields.each do |field|
@@ -271,5 +338,19 @@ module DnsMadeEasy
271
338
  }
272
339
  return default_headers.merge( more_headers )
273
340
  end
341
+
342
+ # Execute a block and handle all the errors it may throw
343
+ def execute_with_caution(namespace={})
344
+ begin
345
+ return yield
346
+ rescue RestClient::BadRequest => e
347
+ error = JSON.parse(e.http_body)
348
+ raise DnsMadeEasy::BadRequestError, error["error"][0]
349
+ rescue RestClient::ResourceNotFound => e
350
+ raise DnsMadeEasy::ResourceNotFoundError, namespace
351
+ rescue RestClient::Forbidden => e
352
+ raise DnsMadeEasy::AuthorizationFailedError
353
+ end
354
+ end
274
355
  end
275
356
  end
@@ -10,31 +10,16 @@ module DnsMadeEasy
10
10
  end
11
11
  end
12
12
 
13
- # Error raised when actions are performed on an domain not listed in the account
14
- class UnknownDomainError < RequestFailedError
15
- def initialize(domain)
16
- super "Domain #{domain} does not exist."
17
- end
18
- end
19
-
20
- # Error raised when an invalid domain is being created
21
- class InvalidDomainNameError < RequestFailedError
22
- def initialize(domain)
23
- super "Domain #{domain} is not valid."
24
- end
25
- end
26
-
27
- # Error raised when a duplicate domain is being created
28
- class DuplicateDomainError < RequestFailedError
29
- def initialize(domain)
30
- super "Domain #{domain} already exists."
31
- end
13
+ # Error raised when the request is bad. Likely causes are exceeding api limits,
14
+ # creating an existing domain/record, or creating a mal-formed record.
15
+ class BadRequestError < RequestFailedError
32
16
  end
33
17
 
34
- # Error raised when an unknown record is being modified or deleted
35
- class UnknownRecordError < RequestFailedError
36
- def initialize(domain, record_id)
37
- super "Record id #{record_id} and/or domain #{domain} does not exist"
18
+ # Error raised when actions are performed against an unknown resource (domain or record)
19
+ class ResourceNotFoundError < RequestFailedError
20
+ def initialize(resource)
21
+ flattened_resource = resource.to_a.map { |x| "#{x[0]}: #{x[1]}" }.join(", ")
22
+ super "Could not find resource - #{flattened_resource}"
38
23
  end
39
24
  end
40
25
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dnsmadeeasy-api
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 49
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- version: "0.9"
9
+ - 5
10
+ version: 0.9.5
10
11
  platform: ruby
11
12
  authors:
12
13
  - Nitesh Goel
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2011-07-06 00:00:00 Z
18
+ date: 2011-07-07 00:00:00 Z
18
19
  dependencies:
19
20
  - !ruby/object:Gem::Dependency
20
21
  name: rest-client
@@ -73,7 +74,7 @@ dependencies:
73
74
  type: :development
74
75
  version_requirements: *id004
75
76
  description: Ruby client for DNSMadeEasy API.
76
- email: nitesh@wikinvest.com
77
+ email: nitesh@sigfig.com
77
78
  executables:
78
79
  - dme
79
80
  extensions: []