dnsimple-ruby 1.2.6 → 1.3.0
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.
- data/.gitignore +3 -0
- data/Gemfile +2 -13
- data/Gemfile.lock +7 -7
- data/Rakefile +2 -18
- data/dnsimple-ruby.gemspec +24 -178
- data/features/support/env.rb +5 -3
- data/lib/dnsimple-ruby.rb +1 -0
- data/lib/dnsimple.rb +1 -0
- data/lib/dnsimple/base.rb +8 -0
- data/lib/dnsimple/certificate.rb +95 -130
- data/lib/dnsimple/client.rb +94 -56
- data/lib/dnsimple/contact.rb +111 -144
- data/lib/dnsimple/domain.rb +145 -194
- data/lib/dnsimple/extended_attribute.rb +33 -60
- data/lib/dnsimple/record.rb +70 -103
- data/lib/dnsimple/service.rb +24 -47
- data/lib/dnsimple/template.rb +47 -75
- data/lib/dnsimple/template_record.rb +53 -84
- data/lib/dnsimple/transfer_order.rb +17 -34
- data/lib/dnsimple/user.rb +18 -32
- data/lib/dnsimple/version.rb +3 -0
- data/spec/commands/purchase_certificate_spec.rb +16 -4
- data/spec/dnsimple/client_spec.rb +58 -0
- data/spec/spec_helper.rb +4 -2
- metadata +59 -92
- data/.bundle/config +0 -3
- data/.rvmrc +0 -1
- data/VERSION +0 -1
data/lib/dnsimple/client.rb
CHANGED
@@ -1,74 +1,112 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
6
|
-
def self.debug=(debug)
|
7
|
-
@debug = debug
|
8
|
-
end
|
1
|
+
class DNSimple::Client
|
2
|
+
def self.debug?
|
3
|
+
@debug
|
4
|
+
end
|
9
5
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
6
|
+
def self.debug=(debug)
|
7
|
+
@debug = debug
|
8
|
+
end
|
14
9
|
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
def self.username
|
11
|
+
@username
|
12
|
+
end
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
14
|
+
def self.username=(username)
|
15
|
+
@username = username
|
16
|
+
end
|
23
17
|
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
def self.password
|
19
|
+
@password
|
20
|
+
end
|
27
21
|
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
def self.password=(password)
|
23
|
+
@password = password
|
24
|
+
end
|
31
25
|
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
def self.api_token
|
27
|
+
@api_token
|
28
|
+
end
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
30
|
+
def self.api_token=(api_token)
|
31
|
+
@api_token = api_token
|
32
|
+
end
|
39
33
|
|
40
|
-
|
41
|
-
|
42
|
-
|
34
|
+
def self.base_uri
|
35
|
+
@base_uri ||= "https://dnsimple.com/"
|
36
|
+
end
|
43
37
|
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
def self.base_uri=(base_uri)
|
39
|
+
base_uri += '/' if base_uri[/\/$/].nil?
|
40
|
+
@base_uri = base_uri
|
41
|
+
end
|
47
42
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
"Credentials loaded from #{path}"
|
56
|
-
rescue
|
57
|
-
puts "Error loading your credentials: #{$!.message}"
|
58
|
-
exit 1
|
59
|
-
end
|
60
|
-
end
|
43
|
+
def self.load_credentials_if_necessary
|
44
|
+
load_credentials unless credentials_loaded?
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.config_path
|
48
|
+
ENV['DNSIMPLE_CONFIG'] || '~/.dnsimple'
|
49
|
+
end
|
61
50
|
|
62
|
-
|
63
|
-
|
51
|
+
def self.load_credentials(path=config_path)
|
52
|
+
begin
|
53
|
+
credentials = YAML.load(File.new(File.expand_path(path)))
|
54
|
+
self.username = credentials['username']
|
55
|
+
self.password = credentials['password']
|
56
|
+
self.api_token = credentials['api_token']
|
57
|
+
self.base_uri = credentials['site']
|
58
|
+
@credentials_loaded = true
|
59
|
+
"Credentials loaded from #{path}"
|
60
|
+
rescue
|
61
|
+
puts "Error loading your credentials: #{$!.message}"
|
62
|
+
exit 1
|
64
63
|
end
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
def self.credentials_loaded?
|
67
|
+
(@credentials_loaded ||= false) or (username and (password or api_token))
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.standard_options
|
71
|
+
options = {:format => :json, :headers => {'Accept' => 'application/json'}}
|
72
|
+
|
73
|
+
if password
|
74
|
+
options[:basic_auth] = {:username => username, :password => password}
|
75
|
+
elsif api_token
|
76
|
+
options[:headers]['X-DNSimple-Token'] = "#{username}:#{api_token}"
|
77
|
+
else
|
78
|
+
raise RuntimeError, 'A password or API token is required for all API requests.'
|
68
79
|
end
|
69
80
|
|
70
|
-
|
71
|
-
|
81
|
+
options
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.get(path, options = {})
|
85
|
+
request :get, path, options
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.post(path, options = {})
|
89
|
+
request :post, path, options
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.put(path, options = {})
|
93
|
+
request :put, path, options
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.delete(path, options = {})
|
97
|
+
request :delete, path, options
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.request(method, path, options)
|
101
|
+
response = HTTParty.send(method, "#{base_uri}#{path}",
|
102
|
+
standard_options.merge(options))
|
103
|
+
|
104
|
+
pp response if debug?
|
105
|
+
|
106
|
+
if response.code == 401
|
107
|
+
raise DNSimple::AuthenticationFailed, 'Authentication failed'
|
72
108
|
end
|
109
|
+
|
110
|
+
response
|
73
111
|
end
|
74
112
|
end
|
data/lib/dnsimple/contact.rb
CHANGED
@@ -1,181 +1,148 @@
|
|
1
|
-
|
2
|
-
# CLass representing a contact in DNSimple
|
3
|
-
class Contact
|
4
|
-
include HTTParty
|
1
|
+
class DNSimple::Contact < DNSimple::Base # Class representing a contact in DNSimple
|
5
2
|
|
6
|
-
|
7
|
-
|
3
|
+
Aliases = {
|
4
|
+
'first' => 'first_name',
|
5
|
+
'last' => 'last_name',
|
6
|
+
'state' => 'state_province',
|
7
|
+
'province' => 'state_province',
|
8
|
+
'state_or_province' => 'state_province',
|
9
|
+
'email' => 'email_address',
|
10
|
+
}
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
attr_accessor :organization_name
|
12
|
+
# The contact ID in DNSimple
|
13
|
+
attr_accessor :id
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
# The name of the organization in which the contact works
|
16
|
+
# (may be omitted)
|
17
|
+
attr_accessor :organization_name
|
15
18
|
|
16
|
-
|
17
|
-
|
19
|
+
# The contact first name
|
20
|
+
attr_accessor :first_name
|
18
21
|
|
19
|
-
|
20
|
-
|
22
|
+
# The contact last name
|
23
|
+
attr_accessor :last_name
|
21
24
|
|
22
|
-
|
23
|
-
|
25
|
+
# The contact's job title (may be omitted)
|
26
|
+
attr_accessor :job_title
|
24
27
|
|
25
|
-
|
26
|
-
|
28
|
+
# The contact street address
|
29
|
+
attr_accessor :address1
|
27
30
|
|
28
|
-
|
29
|
-
|
31
|
+
# Apartment or suite number
|
32
|
+
attr_accessor :address2
|
30
33
|
|
31
|
-
|
32
|
-
|
34
|
+
# The city name
|
35
|
+
attr_accessor :city
|
33
36
|
|
34
|
-
|
35
|
-
|
37
|
+
# The state or province name
|
38
|
+
attr_accessor :state_province
|
36
39
|
|
37
|
-
|
38
|
-
|
40
|
+
# The contact postal code
|
41
|
+
attr_accessor :postal_code
|
39
42
|
|
40
|
-
|
41
|
-
|
43
|
+
# The contact country (as a 2-character country code)
|
44
|
+
attr_accessor :country
|
42
45
|
|
43
|
-
|
44
|
-
|
46
|
+
# The contact email address
|
47
|
+
attr_accessor :email_address
|
45
48
|
|
46
|
-
|
47
|
-
|
49
|
+
# The contact phone number
|
50
|
+
attr_accessor :phone
|
48
51
|
|
49
|
-
|
50
|
-
|
52
|
+
# The contact phone extension (may be omitted)
|
53
|
+
attr_accessor :phone_ext
|
51
54
|
|
52
|
-
|
53
|
-
|
55
|
+
# The contact fax number (may be omitted)
|
56
|
+
attr_accessor :fax
|
54
57
|
|
55
|
-
|
56
|
-
|
58
|
+
# When the contact was created in DNSimple
|
59
|
+
attr_accessor :created_at
|
57
60
|
|
58
|
-
|
59
|
-
|
60
|
-
attributes.each do |key, value|
|
61
|
-
m = "#{key}=".to_sym
|
62
|
-
self.send(m, value) if self.respond_to?(m)
|
63
|
-
end
|
64
|
-
end
|
61
|
+
# When the contact was last updated in DNSimple
|
62
|
+
attr_accessor :updated_at
|
65
63
|
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
def name
|
65
|
+
[first_name, last_name].join(' ')
|
66
|
+
end
|
69
67
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
options.merge!(DNSimple::Client.standard_options_with_credentials)
|
78
|
-
options.merge!({:body => {:contact => contact_hash}})
|
79
|
-
|
80
|
-
response = self.class.put("#{Client.base_uri}/contacts/#{id}", options)
|
81
|
-
|
82
|
-
pp response if Client.debug?
|
83
|
-
|
84
|
-
case response.code
|
85
|
-
when 200
|
86
|
-
return self
|
87
|
-
when 401
|
88
|
-
raise RuntimeError, "Authentication failed"
|
89
|
-
else
|
90
|
-
raise RuntimeError, "Failed to update contact: #{response.inspect}"
|
91
|
-
end
|
68
|
+
def save(options={})
|
69
|
+
contact_hash = {}
|
70
|
+
%w(first_name last_name organization_name job_title address1 address2 city
|
71
|
+
state_province postal_code country email_address phone phone_ext fax).each do |attribute|
|
72
|
+
contact_hash[DNSimple::Contact.resolve(attribute)] = self.send(attribute)
|
92
73
|
end
|
93
74
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
self.class.delete("#{Client.base_uri}/contacts/#{id}.json", options)
|
98
|
-
end
|
99
|
-
alias :destroy :delete
|
100
|
-
|
101
|
-
# Map an aliased field name to it's real name. For example, if you
|
102
|
-
# pass "first" it will be resolved to "first_name", "email" is resolved
|
103
|
-
# to "email_address" and so on.
|
104
|
-
def self.resolve(name)
|
105
|
-
aliases = {
|
106
|
-
'first' => 'first_name',
|
107
|
-
'last' => 'last_name',
|
108
|
-
'state' => 'state_province',
|
109
|
-
'province' => 'state_province',
|
110
|
-
'state_or_province' => 'state_province',
|
111
|
-
'email' => 'email_address',
|
112
|
-
}
|
113
|
-
aliases[name.to_s] || name
|
114
|
-
end
|
75
|
+
options.merge!({:body => {:contact => contact_hash}})
|
76
|
+
|
77
|
+
response = DNSimple::Client.put("contacts/#{id}", options)
|
115
78
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
resolved_attributes
|
79
|
+
case response.code
|
80
|
+
when 200
|
81
|
+
return self
|
82
|
+
else
|
83
|
+
raise RuntimeError, "Failed to update contact: #{response.inspect}"
|
122
84
|
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Delete the contact from DNSimple. WARNING: this cannot be undone.
|
88
|
+
def delete(options={})
|
89
|
+
DNSimple::Client.delete("contacts/#{id}.json", options)
|
90
|
+
end
|
91
|
+
alias :destroy :delete
|
123
92
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
93
|
+
# Map an aliased field name to it's real name. For example, if you
|
94
|
+
# pass "first" it will be resolved to "first_name", "email" is resolved
|
95
|
+
# to "email_address" and so on.
|
96
|
+
def self.resolve(name)
|
97
|
+
DNSimple::Contact::Aliases[name.to_s] || name
|
98
|
+
end
|
129
99
|
|
130
|
-
|
131
|
-
|
100
|
+
def self.resolve_attributes(attributes)
|
101
|
+
resolved_attributes = {}
|
102
|
+
attributes.each do |k, v|
|
103
|
+
resolved_attributes[resolve(k)] = v
|
104
|
+
end
|
105
|
+
resolved_attributes
|
106
|
+
end
|
132
107
|
|
133
|
-
|
108
|
+
# Create the contact with the given attributes in DNSimple.
|
109
|
+
# This method returns a Contact instance of the contact is created
|
110
|
+
# and raises an error otherwise.
|
111
|
+
def self.create(attributes, options={})
|
112
|
+
contact_hash = resolve_attributes(attributes)
|
134
113
|
|
135
|
-
|
114
|
+
options.merge!({:body => {:contact => contact_hash}})
|
115
|
+
response = DNSimple::Client.post 'contacts.json', options
|
136
116
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
else
|
143
|
-
raise RuntimeError, "Failed to create contact: #{response.inspect}"
|
144
|
-
end
|
117
|
+
case response.code
|
118
|
+
when 201
|
119
|
+
return new(response["contact"])
|
120
|
+
else
|
121
|
+
raise RuntimeError, "Failed to create contact: #{response.inspect}"
|
145
122
|
end
|
123
|
+
end
|
146
124
|
|
147
|
-
|
148
|
-
|
149
|
-
response = self.get("#{Client.base_uri}/contacts/#{id}.json", options)
|
150
|
-
|
151
|
-
pp response if Client.debug?
|
152
|
-
|
153
|
-
case response.code
|
154
|
-
when 200
|
155
|
-
return Contact.new(response["contact"])
|
156
|
-
when 401
|
157
|
-
raise RuntimeError, "Authentication failed"
|
158
|
-
when 404
|
159
|
-
raise RuntimeError, "Could not find contact #{id}"
|
160
|
-
else
|
161
|
-
raise DNSimple::Error.new(id, response["errors"])
|
162
|
-
end
|
163
|
-
end
|
125
|
+
def self.find(id, options={})
|
126
|
+
response = DNSimple::Client.get "contacts/#{id}.json", options
|
164
127
|
|
165
|
-
|
166
|
-
|
167
|
-
|
128
|
+
case response.code
|
129
|
+
when 200
|
130
|
+
return new(response["contact"])
|
131
|
+
when 404
|
132
|
+
raise RuntimeError, "Could not find contact #{id}"
|
133
|
+
else
|
134
|
+
raise DNSimple::Error.new(id, response["errors"])
|
135
|
+
end
|
136
|
+
end
|
168
137
|
|
169
|
-
|
138
|
+
def self.all(options={})
|
139
|
+
response = DNSimple::Client.get 'contacts.json', options
|
170
140
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
else
|
177
|
-
raise RuntimeError, "Error: #{response.code}"
|
178
|
-
end
|
141
|
+
case response.code
|
142
|
+
when 200
|
143
|
+
response.map { |r| new(r["contact"]) }
|
144
|
+
else
|
145
|
+
raise RuntimeError, "Error: #{response.code}"
|
179
146
|
end
|
180
147
|
end
|
181
148
|
end
|