zonomi 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +87 -0
- data/Rakefile +1 -0
- data/lib/zonomi.rb +8 -0
- data/lib/zonomi/api.rb +28 -0
- data/lib/zonomi/api/action.rb +87 -0
- data/lib/zonomi/api/adapter.rb +188 -0
- data/lib/zonomi/api/client.rb +43 -0
- data/lib/zonomi/api/record.rb +6 -0
- data/lib/zonomi/api/request.rb +55 -0
- data/lib/zonomi/api/result.rb +6 -0
- data/lib/zonomi/api/zone.rb +6 -0
- data/lib/zonomi/version.rb +3 -0
- data/spec/api/action_spec.rb +49 -0
- data/spec/api/client_spec.rb +20 -0
- data/spec/factories.rb +10 -0
- data/spec/factories_spec.rb +14 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/zonomi_spec.rb +16 -0
- data/zonomi.gemspec +30 -0
- data/zonomi_api_description.txt +40 -0
- metadata +154 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'bundler' do
|
5
|
+
watch('Gemfile')
|
6
|
+
watch(%r{^.+\.gemspec})
|
7
|
+
end
|
8
|
+
|
9
|
+
guard 'rspec', :version => 2, :cli => "--color --format nested --fail-fast" do
|
10
|
+
watch(%r{^spec/.+_spec\.rb$})
|
11
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
12
|
+
watch('spec/spec_helper.rb') { "spec" }
|
13
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Ruby Cluster, Vlad Alive
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# Zonomi
|
2
|
+
|
3
|
+
Zonomi DNS API wrapper written in Ruby.
|
4
|
+
|
5
|
+
> https://zonomi.com/app/dns/dyndns.jsp
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
### API Client
|
10
|
+
|
11
|
+
First create new API client instance:
|
12
|
+
|
13
|
+
client = Zonomi::API::Client.new(api_key: "YOUR_API_KEY")
|
14
|
+
|
15
|
+
> Zonomi API keys are managed at: https://zonomi.com/app/cp/apikeys.jsp
|
16
|
+
|
17
|
+
### API actions
|
18
|
+
|
19
|
+
All actions are performed via:
|
20
|
+
|
21
|
+
client.api
|
22
|
+
|
23
|
+
#### Records
|
24
|
+
|
25
|
+
Fetch all DNS records by name:
|
26
|
+
|
27
|
+
client.api.records_by_name(name)
|
28
|
+
|
29
|
+
Fetch all DNS records ending with name:
|
30
|
+
|
31
|
+
client.api.records_by_name(name, all_records: true)
|
32
|
+
|
33
|
+
IP address:
|
34
|
+
|
35
|
+
client.api.set_current_ipaddress_to_host(host)
|
36
|
+
client.api.change_ip(old_ip, new_ip)
|
37
|
+
|
38
|
+
A type records:
|
39
|
+
|
40
|
+
client.api.set_ipaddress_for_a_record_for(name, value)
|
41
|
+
client.api.delete_ipaddress_for_a_record_for(name)
|
42
|
+
|
43
|
+
MX type records:
|
44
|
+
|
45
|
+
client.api.set_mx_record_for(name, value, prio = 5)
|
46
|
+
|
47
|
+
#### Zones:
|
48
|
+
|
49
|
+
Fetch all DNS zones:
|
50
|
+
|
51
|
+
client.api.zones
|
52
|
+
|
53
|
+
Manage DNS zones:
|
54
|
+
|
55
|
+
client.api.add_zone(name)
|
56
|
+
client.api.delete_zone(name)
|
57
|
+
client.api.convert_zone_to_master(name)
|
58
|
+
client.api.convert_zone_to_slave(name, master)
|
59
|
+
|
60
|
+
## Installation
|
61
|
+
|
62
|
+
Add this line to your application's Gemfile:
|
63
|
+
|
64
|
+
gem 'zonomi'
|
65
|
+
|
66
|
+
And then execute:
|
67
|
+
|
68
|
+
$ bundle
|
69
|
+
|
70
|
+
Or install it yourself as:
|
71
|
+
|
72
|
+
$ gem install zonomi
|
73
|
+
|
74
|
+
## TODO
|
75
|
+
|
76
|
+
- Records and Zones should have active methods
|
77
|
+
- Command line tool
|
78
|
+
- Better test coverage
|
79
|
+
- Better documentation
|
80
|
+
|
81
|
+
## Contributing
|
82
|
+
|
83
|
+
1. Fork it
|
84
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
85
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
86
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
87
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/zonomi.rb
ADDED
data/lib/zonomi/api.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Zonomi
|
2
|
+
module API
|
3
|
+
|
4
|
+
SERVER = {
|
5
|
+
domain: 'https://zonomi.com',
|
6
|
+
prefix: '/app/dns',
|
7
|
+
suffix: '.jsp',
|
8
|
+
routes: {
|
9
|
+
dyndns: '/dyndns',
|
10
|
+
zone: {
|
11
|
+
add: '/addzone',
|
12
|
+
to_slave: '/converttosecondary',
|
13
|
+
to_master: '/converttomaster',
|
14
|
+
},
|
15
|
+
ipchange: '/ipchange',
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
require_relative "api/adapter"
|
20
|
+
require_relative "api/client"
|
21
|
+
require_relative "api/request"
|
22
|
+
require_relative "api/action"
|
23
|
+
require_relative "api/record"
|
24
|
+
require_relative "api/zone"
|
25
|
+
require_relative "api/result"
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Zonomi::API
|
2
|
+
|
3
|
+
class Action < OpenStruct
|
4
|
+
|
5
|
+
ATTRIBUTES = [:action, :host, :name, :type, :value, :prio, :ttl]
|
6
|
+
ACTIONS = {
|
7
|
+
set: 'SET',
|
8
|
+
query: 'QUERY',
|
9
|
+
delete: 'DELETE',
|
10
|
+
delete_zone: 'DELETEZONE',
|
11
|
+
query_zones: 'QUERYZONES',
|
12
|
+
}
|
13
|
+
TYPES = {
|
14
|
+
a: 'A',
|
15
|
+
mx: 'MX',
|
16
|
+
txt: 'TXT',
|
17
|
+
}
|
18
|
+
|
19
|
+
def attributes
|
20
|
+
get_allowed_attributes
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_hash
|
24
|
+
format_attributes
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
attributes_to_params
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_param
|
32
|
+
attributes_to_params
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid?
|
36
|
+
validate_attributes!
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def get_allowed_attributes
|
42
|
+
ATTRIBUTES.reduce({}) do |a,i|
|
43
|
+
value = self.send(:"#{i}")
|
44
|
+
if value
|
45
|
+
a[i] = value
|
46
|
+
end
|
47
|
+
a
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate_attributes!
|
52
|
+
validate_attributes_values!
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_attributes_values!
|
56
|
+
conditions = [
|
57
|
+
(attributes.has_key?(:action) ? ACTIONS.keys.include?(attributes[:action]) : true),
|
58
|
+
(attributes.has_key?(:type) ? TYPES. keys.include?(attributes[:type ]) : true),
|
59
|
+
]
|
60
|
+
conditions.include?(false) ? raise(ArgumentError, 'Bad attributes values') : true
|
61
|
+
end
|
62
|
+
|
63
|
+
def format_attributes
|
64
|
+
attrs = {}
|
65
|
+
attributes.each do |k,v|
|
66
|
+
attrs[k] = case k
|
67
|
+
when :action
|
68
|
+
ACTIONS[v]
|
69
|
+
when :type
|
70
|
+
TYPES[v]
|
71
|
+
else
|
72
|
+
v
|
73
|
+
end
|
74
|
+
end
|
75
|
+
attrs
|
76
|
+
end
|
77
|
+
|
78
|
+
def attributes_to_params
|
79
|
+
format_attributes.map.sort_by(&:first).
|
80
|
+
map{ |k, v|
|
81
|
+
[k,v].join('=')
|
82
|
+
}.join('&')
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
module Zonomi::API
|
2
|
+
|
3
|
+
class Adapter
|
4
|
+
|
5
|
+
attr_reader :client, :actions, :requests, :responses, :results
|
6
|
+
|
7
|
+
def initialize(client)
|
8
|
+
@client = client
|
9
|
+
@actions = []
|
10
|
+
@requests = []
|
11
|
+
@responses = []
|
12
|
+
@results = []
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
# Set the IP Address for 'some-test-domain.com' to your PC's address. Right now that is 176.52.37.118.
|
17
|
+
# https://zonomi.com/app/dns/dyndns.jsp?host=some-test-domain.com&api_key=api_key_hash
|
18
|
+
|
19
|
+
def set_current_ipaddress_to_host(host)
|
20
|
+
query!(:set_current_ipaddress_to_host, host: host)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Set an IP Address (A) record
|
24
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action=SET&name=some-test-domain.com&value=10.0.0.1&type=A&api_key=api_key_hash
|
25
|
+
|
26
|
+
def set_ipaddress_for_a_record_for(name, value)
|
27
|
+
query!(:set_ipaddress_for_a_record_for, name: name, value: value)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Delete an IP Address (A) record
|
31
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action=DELETE&name=some-test-domain.com&type=A&api_key=api_key_hash
|
32
|
+
|
33
|
+
def delete_ipaddress_for_a_record_for(name)
|
34
|
+
query!(:delete_ipaddress_for_a_record_for, name: name)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Set an MX Record
|
38
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action=SET&name=some-test-domain.com&value=mail.some-test-domain.com&type=MX&prio=5&api_key=api_key_hash
|
39
|
+
|
40
|
+
def set_mx_record_for(name, value, prio = 5)
|
41
|
+
query!(:set_mx_record_for, name: name, value: value, prio: prio)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Retrieve a list of records with the specified name.
|
45
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action=QUERY&name=some-test-domain.com&api_key=api_key_hash
|
46
|
+
|
47
|
+
# Retrieve all records ending in some-test-domain.com. e.g. letting you fetch all records in a DNS zone.
|
48
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action=QUERY&name=**.some-test-domain.com&api_key=api_key_hash
|
49
|
+
|
50
|
+
def records_by_name(name, options = {})
|
51
|
+
all_records = options.delete(:all_records) || false
|
52
|
+
if all_records
|
53
|
+
name.gsub!(%r{^\W+}, '')
|
54
|
+
name = '**.' + name
|
55
|
+
end
|
56
|
+
|
57
|
+
query!(:records_by_name, name: name)
|
58
|
+
respond_value_for(results.last, :records_by_name).map do |record_hash|
|
59
|
+
Record.new(record_hash)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Multiple actions: set two records to the same IP and delete the bar.some-test-domain.com IP Address (A) record.
|
64
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action[1]=SET&name[1]=some-test-domain.com,bar.some-test-domain.com&value[1]=10.0.0.1&action[2]=DELETE&host[2]=bar.some-test-domain.com&api_key=api_key_hash
|
65
|
+
|
66
|
+
# Multiple actions: set multiple different values for a particular name. e.g. for setting multiple MX servers (like with gmail).
|
67
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action[1]=SET&name[1]=some-test-domain.com&value[1]=ASPMX.L.GOOGLE.COM&prio[1]=1&type[1]=MX&action[2]=SET&name[2]=some-test-domain.com&value[2]=ALT1.ASPMX.L.GOOGLE.COM&prio[2]=2&type[2]=MX&action[3]=SET&name[3]=some-test-domain.com&value[3]=ALT2.ASPMX.L.GOOGLE.COM&prio[3]=3&type[3]=MX&action[4]=SET&name[4]=some-test-domain.com&value[4]=ASPMX2.GOOGLEMAIL.COM&prio[4]=4&type[4]=MX&action[5]=SET&name[5]=some-test-domain.com&value[5]=ASPMX3.GOOGLEMAIL.COM&prio[5]=5&type[5]=MX&api_key=api_key_hash
|
68
|
+
|
69
|
+
# Setup a new DNS zone.
|
70
|
+
# https://zonomi.com/app/dns/addzone.jsp?name=some-test-domain.com&api_key=api_key_hash
|
71
|
+
|
72
|
+
def add_zone(name)
|
73
|
+
query!(:add_zone, name: name)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Delete a DNS zone.
|
77
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action=DELETEZONE&name=some-test-domain.com&api_key=api_key_hash
|
78
|
+
|
79
|
+
def delete_zone(name)
|
80
|
+
query!(:delete_zone, name: name)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Return a list of zones on your account.
|
84
|
+
# https://zonomi.com/app/dns/dyndns.jsp?action=QUERYZONES&api_key=api_key_hash
|
85
|
+
|
86
|
+
def zones
|
87
|
+
query!(:zones)
|
88
|
+
respond_value_for(results.last, :zones).map do |zone_hash|
|
89
|
+
Zone.new(zone_hash)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Convert a zone to a slave zone with the specified master name server IP address.
|
94
|
+
# https://zonomi.com/app/dns/converttosecondary.jsp?name=some-test-domain.com&master=0.0.0.0&api_key=api_key_hash
|
95
|
+
|
96
|
+
def convert_zone_to_slave(name, master)
|
97
|
+
query!(:convert_zone_to_slave, name: name, master: master)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Convert a zone from a slave zone back to a 'regular' zone (where you manage your DNS records via our web pages and API).
|
101
|
+
# https://zonomi.com/app/dns/converttomaster.jsp?name=some-test-domain.com&api_key=api_key_hash
|
102
|
+
|
103
|
+
def convert_zone_to_master(name)
|
104
|
+
query!(:convert_zone_to_master, name: name)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Change an IP across all your zones.
|
108
|
+
# https://zonomi.com/app/dns/ipchange.jsp?old_ip=0.0.0.0&new_ip=0.0.0.0&api_key=api_key_hash
|
109
|
+
|
110
|
+
def change_ip(old_ip, new_ip)
|
111
|
+
query!(:change_ip, old_ip: old_ip, new_ip: new_ip)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Multiple actions: set two records to the same IP and delete the
|
115
|
+
# bar.some-test-domain.com IP Address (A) record
|
116
|
+
|
117
|
+
# Multiple actions: set multiple different values for a particular
|
118
|
+
# name. e.g. for setting multiple MX servers (like with gmail).
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def query!(result_type, params = {})
|
123
|
+
action = Action.new(action_params(result_type, params))
|
124
|
+
action.valid?
|
125
|
+
request_params = action.to_hash.merge({
|
126
|
+
request_path: path_for_result_type(result_type)
|
127
|
+
})
|
128
|
+
request = self.client.api_request(request_params)
|
129
|
+
request.send!
|
130
|
+
|
131
|
+
@actions << action
|
132
|
+
@requests << request
|
133
|
+
@responses << request.response
|
134
|
+
@results << request.result
|
135
|
+
|
136
|
+
self
|
137
|
+
end
|
138
|
+
|
139
|
+
def action_params(result_type, params)
|
140
|
+
default_action_params(result_type).merge(params)
|
141
|
+
end
|
142
|
+
|
143
|
+
def default_action_params(result_type)
|
144
|
+
case result_type
|
145
|
+
when :records_by_name
|
146
|
+
{ action: :query }
|
147
|
+
when :set_ipaddress_for_a_record_for
|
148
|
+
{ action: :set, type: :a }
|
149
|
+
when :delete_ipaddress_for_a_record_for
|
150
|
+
{ action: :delete, type: :a }
|
151
|
+
when :set_mx_record_for
|
152
|
+
{ action: :set, type: :mx, prio: 5 }
|
153
|
+
when :delete_zone
|
154
|
+
{ action: :delete_zone }
|
155
|
+
when :zones
|
156
|
+
{ action: :query_zones }
|
157
|
+
else
|
158
|
+
{}
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def path_for_result_type(result_type)
|
163
|
+
case result_type
|
164
|
+
when :add_zone
|
165
|
+
[:zone, :add]
|
166
|
+
when :convert_zone_to_slave
|
167
|
+
[:zone, :to_slave]
|
168
|
+
when :convert_zone_to_master
|
169
|
+
[:zone, :to_master]
|
170
|
+
when :change_ip
|
171
|
+
:ipchange
|
172
|
+
else
|
173
|
+
:dyndns
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def respond_value_for(result, result_type)
|
178
|
+
case result_type
|
179
|
+
when :records_by_name
|
180
|
+
result.actions['action']['record']
|
181
|
+
when :zones
|
182
|
+
result.actions['action']['zone']
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Zonomi::API
|
2
|
+
|
3
|
+
class Client
|
4
|
+
|
5
|
+
include HTTParty
|
6
|
+
|
7
|
+
def self.server_base_uri
|
8
|
+
[
|
9
|
+
SERVER[:domain],
|
10
|
+
SERVER[:prefix]
|
11
|
+
].join
|
12
|
+
end
|
13
|
+
|
14
|
+
base_uri self.server_base_uri
|
15
|
+
format :xml
|
16
|
+
|
17
|
+
attr_accessor :api_key
|
18
|
+
attr_reader :api
|
19
|
+
|
20
|
+
def initialize(*args)
|
21
|
+
# options = args.extract_options!
|
22
|
+
options = args.last.is_a?(::Hash) ? args.pop : {}
|
23
|
+
@api_key = ! args[0].nil? ? args[0] : options.delete(:api_key) || ''
|
24
|
+
@api = Adapter.new(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def api_request(params)
|
28
|
+
Request.new(params.merge(client: self))
|
29
|
+
end
|
30
|
+
|
31
|
+
def valid?
|
32
|
+
validate!
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def validate!
|
38
|
+
! @api_key.nil? && ( @api_key.is_a?(String) || @api_key.is_a?(Integer) ) && @api_key.size > 0
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Zonomi::API
|
2
|
+
|
3
|
+
class Request
|
4
|
+
|
5
|
+
REQUEST_METHOD = :get
|
6
|
+
RESULT_KEY = 'dnsapi_result'
|
7
|
+
|
8
|
+
attr_reader :params, :client, :response, :result
|
9
|
+
|
10
|
+
def initialize(params = {})
|
11
|
+
@params = params
|
12
|
+
@client = @params.delete(:client)
|
13
|
+
@request_path = @params.delete(:request_path)
|
14
|
+
@response = nil
|
15
|
+
@result = nil
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def send!
|
20
|
+
request_params = [
|
21
|
+
REQUEST_METHOD,
|
22
|
+
path_for(*@request_path),
|
23
|
+
{ query: prepare(@params) }
|
24
|
+
]
|
25
|
+
@response = self.client.class.send(*request_params)
|
26
|
+
@result = Result.new(@response[RESULT_KEY])
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def prepare(params)
|
33
|
+
default_params.merge(params)
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_params
|
37
|
+
{
|
38
|
+
api_key: self.client.api_key,
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def path_for(*api_type)
|
43
|
+
path = api_type.reduce(SERVER[:routes]){ |a,i| a[i] }
|
44
|
+
if path.nil? || path.is_a?(Hash)
|
45
|
+
path = SERVER[:routes][:dyndns]
|
46
|
+
end
|
47
|
+
[
|
48
|
+
path,
|
49
|
+
SERVER[:suffix],
|
50
|
+
].join
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zonomi::API::Action do
|
4
|
+
|
5
|
+
let(:domain_name) { TEST_DOMAIN_NAME }
|
6
|
+
|
7
|
+
context "valid" do
|
8
|
+
|
9
|
+
context 'should accept attributes' do
|
10
|
+
|
11
|
+
describe 'action, name' do
|
12
|
+
subject { build(:action, action: :query, name: domain_name) }
|
13
|
+
its(:name) { should == domain_name }
|
14
|
+
its(:action) { should == :query }
|
15
|
+
its(:attributes) { should == { action: :query, name: domain_name } }
|
16
|
+
its(:to_hash) { should == { action: 'QUERY', name: domain_name } }
|
17
|
+
its(:to_param) { should == "action=QUERY&name=#{domain_name}" }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'and preserve keys order in hash' do
|
21
|
+
subject { build(:action, value: '127.0.0.1', type: :a, action: :set, name: domain_name) }
|
22
|
+
its(:to_param) { should == "action=SET&name=#{domain_name}&type=A&value=127.0.0.1" }
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
context "invalid" do
|
30
|
+
|
31
|
+
describe "with bad attributes keys" do
|
32
|
+
pending
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "with bad attributes values" do
|
36
|
+
bad_attributes_scenarios = [
|
37
|
+
{ action: :hack },
|
38
|
+
{ type: :root },
|
39
|
+
]
|
40
|
+
bad_attributes_scenarios.each_with_index do |bad_attributes, index|
|
41
|
+
it "Scenario ##{index + 1}: should raise an argument error" do
|
42
|
+
expect { build(:action, bad_attributes).valid? }.to raise_error(ArgumentError)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zonomi::API::Client do
|
4
|
+
|
5
|
+
before(:all) {
|
6
|
+
@client = build(:client)
|
7
|
+
}
|
8
|
+
|
9
|
+
subject { @client }
|
10
|
+
|
11
|
+
it { should respond_to(:api_key) }
|
12
|
+
its(:api_key) { should eq(TEST_API_KEY) }
|
13
|
+
|
14
|
+
it { should respond_to(:api) }
|
15
|
+
its(:api) { should be_a_kind_of(Zonomi::API::Adapter) }
|
16
|
+
|
17
|
+
it { should respond_to(:api_request) }
|
18
|
+
it { should respond_to(:api_request).with(1).arguments }
|
19
|
+
|
20
|
+
end
|
data/spec/factories.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'validate FactoryGirl factories' do
|
4
|
+
FactoryGirl.factories.each do |factory|
|
5
|
+
context "with factory for :#{factory.name}" do
|
6
|
+
subject { FactoryGirl.build(factory.name) }
|
7
|
+
|
8
|
+
it "is valid" do
|
9
|
+
# subject.valid?.should be, subject.errors.full_messages
|
10
|
+
subject.valid?.should be
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
|
3
|
+
require_relative '../lib/zonomi.rb'
|
4
|
+
|
5
|
+
# Define your real api_key
|
6
|
+
TEST_API_KEY = ENV["ZONOMI_TEST_API_KEY"]
|
7
|
+
|
8
|
+
# Define your real test domain
|
9
|
+
TEST_DOMAIN_NAME = ENV["ZONOMI_TEST_DOMAIN_NAME"]
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.include FactoryGirl::Syntax::Methods
|
13
|
+
end
|
14
|
+
|
15
|
+
FactoryGirl.find_definitions
|
data/spec/zonomi_spec.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zonomi do
|
4
|
+
|
5
|
+
specify { TEST_API_KEY.should_not be_nil }
|
6
|
+
specify { TEST_DOMAIN_NAME.should_not be_nil }
|
7
|
+
|
8
|
+
subject { Zonomi }
|
9
|
+
|
10
|
+
it { should be_a(Module) }
|
11
|
+
its(:constants) { should include(:'VERSION', :'API') }
|
12
|
+
it "should have a valid version" do
|
13
|
+
subject::VERSION.should =~ %r{^(\d*\.){2,3}(\d|\w*)$}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/zonomi.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'zonomi/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "zonomi"
|
8
|
+
gem.version = Zonomi::VERSION
|
9
|
+
gem.authors = ["Ruby Cluster", "Vlad Alive"]
|
10
|
+
gem.email = ["gems@rubycluster.com"]
|
11
|
+
gem.description = %q{Zonomi API Ruby wrapper}
|
12
|
+
gem.summary = %q{Zonomi API Ruby wrapper}
|
13
|
+
gem.homepage = "http://github.com/rubycluster/zonomi"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency "httparty", ">= 0"
|
21
|
+
|
22
|
+
gem.add_development_dependency "guard"
|
23
|
+
gem.add_development_dependency "guard-bundler"
|
24
|
+
gem.add_development_dependency "guard-rspec"
|
25
|
+
gem.add_development_dependency "rb-inotify", "~> 0.8.8"
|
26
|
+
|
27
|
+
gem.add_development_dependency "rspec", "~> 2.6"
|
28
|
+
gem.add_development_dependency "factory_girl"
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# DNS API Reference
|
2
|
+
# Parameter Name; Parameter Alias
|
3
|
+
# Description
|
4
|
+
|
5
|
+
# action
|
6
|
+
# One of SET (the default), QUERY or DELETE.
|
7
|
+
# If you set a hostname that does not already exist in a zone, the hostname will be added to that zone. If you delete a record that does not exist the request will be ignored.
|
8
|
+
# host; hostname
|
9
|
+
# The dns record you are updating.
|
10
|
+
# This field is required.
|
11
|
+
# You must have a zone setup on our name servers with this host in it. e.g. if you have an example.com zone setup you could have host=example.com or host=www.example.com. This API will not create zones on the fly. The zone must not be a 'slave' zone on our servers (in which case it is read-only). You can provide one or more (comma separated) host values. e.g. if you wanted to set multiple domain names to a single IP addresss. Use **.example.com to match all names ending in example.com. This can be useful for getting a list of all records in a zone.
|
12
|
+
# type
|
13
|
+
# DNS record type.
|
14
|
+
# e.g. A, MX, or TXT.
|
15
|
+
# Defaults to A.
|
16
|
+
# value; myip, dnsto
|
17
|
+
# Set this value on the record.
|
18
|
+
# If the record is an IP Address (A) record then the value would need to be an IP address. If the record were a Mail Server (MX) record then it would need to be a host name. For an IP Address (A) record this will default to the IP address of the API client (e.g. your home PC, e.g. right now that is 176.52.37.118). To set multiple values for a single hostname provide a comma separated list of values. e.g. if you wanted to set multiple IPs for a IP Address (A) record. The multiple values feature only works with some (e.g. PTR, A, MX, CNAME) record types.
|
19
|
+
# prio
|
20
|
+
# The priority.
|
21
|
+
# A number.
|
22
|
+
# Used on MX records.
|
23
|
+
# If not specified the API will set it to 0. If more than one host name is specified for the action and the priority is not specified then the priority is incremented for each host.
|
24
|
+
# ttl
|
25
|
+
# The TTL (time to live) on the record.
|
26
|
+
# Optional (and typically best not provided).
|
27
|
+
# A number.
|
28
|
+
# Used to hint at how long in minutes recursive name servers should cache the record details. 3600 or one hour is a common default.
|
29
|
+
# api_key
|
30
|
+
# Your DNS API key.
|
31
|
+
# Keep this secret (like you would a password).
|
32
|
+
# This API key is unique to your user account.
|
33
|
+
# Your API key can be passed in as an api_key=blah parameter. Or it can be passed in as an 'Authorization' header. The format for the Authorization header is like "Authorization: redrata api_key=ec7....82e137431". To change your API key (e.g. if someone who should not know it discovers it) use our API keys page. Your API Key is api_key_hash.
|
34
|
+
|
35
|
+
# If you wish to perform more than one action add [number] to each parameter in that action set. The actions will be performed in numerical order.
|
36
|
+
# You can use either the https URL or a plain http URL. If your dynamic DNS client supports it, we recommend the https URL since then the URL is encrypted.
|
37
|
+
# You can use GET (with the parameters in the URL) or POST (with the parameters as form URL encoded values).
|
38
|
+
# If the update is successful you will get page a page with one line of text that starts "OK:". If the update fails you will get back a page with one line of text that starts "ERROR:".
|
39
|
+
|
40
|
+
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zonomi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ruby Cluster
|
9
|
+
- Vlad Alive
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-10-07 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: httparty
|
17
|
+
requirement: &82350180 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *82350180
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: guard
|
28
|
+
requirement: &82349950 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *82349950
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: guard-bundler
|
39
|
+
requirement: &82349710 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *82349710
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: guard-rspec
|
50
|
+
requirement: &82349500 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *82349500
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rb-inotify
|
61
|
+
requirement: &82349230 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ~>
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 0.8.8
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *82349230
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
requirement: &82348980 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '2.6'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *82348980
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: factory_girl
|
83
|
+
requirement: &82348790 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *82348790
|
92
|
+
description: Zonomi API Ruby wrapper
|
93
|
+
email:
|
94
|
+
- gems@rubycluster.com
|
95
|
+
executables: []
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files: []
|
98
|
+
files:
|
99
|
+
- .gitignore
|
100
|
+
- Gemfile
|
101
|
+
- Guardfile
|
102
|
+
- LICENSE.txt
|
103
|
+
- README.md
|
104
|
+
- Rakefile
|
105
|
+
- lib/zonomi.rb
|
106
|
+
- lib/zonomi/api.rb
|
107
|
+
- lib/zonomi/api/action.rb
|
108
|
+
- lib/zonomi/api/adapter.rb
|
109
|
+
- lib/zonomi/api/client.rb
|
110
|
+
- lib/zonomi/api/record.rb
|
111
|
+
- lib/zonomi/api/request.rb
|
112
|
+
- lib/zonomi/api/result.rb
|
113
|
+
- lib/zonomi/api/zone.rb
|
114
|
+
- lib/zonomi/version.rb
|
115
|
+
- spec/api/action_spec.rb
|
116
|
+
- spec/api/client_spec.rb
|
117
|
+
- spec/factories.rb
|
118
|
+
- spec/factories_spec.rb
|
119
|
+
- spec/spec_helper.rb
|
120
|
+
- spec/zonomi_spec.rb
|
121
|
+
- zonomi.gemspec
|
122
|
+
- zonomi_api_description.txt
|
123
|
+
homepage: http://github.com/rubycluster/zonomi
|
124
|
+
licenses: []
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ! '>='
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
requirements: []
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 1.8.10
|
144
|
+
signing_key:
|
145
|
+
specification_version: 3
|
146
|
+
summary: Zonomi API Ruby wrapper
|
147
|
+
test_files:
|
148
|
+
- spec/api/action_spec.rb
|
149
|
+
- spec/api/client_spec.rb
|
150
|
+
- spec/factories.rb
|
151
|
+
- spec/factories_spec.rb
|
152
|
+
- spec/spec_helper.rb
|
153
|
+
- spec/zonomi_spec.rb
|
154
|
+
has_rdoc:
|