esgob 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +2 -2
- data/bin/esgob +8 -0
- data/esgob.gemspec +13 -11
- data/lib/esgob/cli.rb +134 -0
- data/lib/esgob/client.rb +89 -25
- data/lib/esgob/version.rb +1 -1
- data/lib/esgob.rb +11 -1
- data/test/esgob_cli_test.rb +129 -0
- data/test/esgob_client_test.rb +118 -29
- data/test/esgob_version_test.rb +0 -2
- data/test/fixtures/code_1003.json +6 -0
- data/test/fixtures/code_2007.json +6 -0
- data/test/fixtures/sync-domain-list.txt +2 -0
- data/test/test_helper.rb +21 -4
- metadata +43 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f029cb699d12ea2f9ebc3d62538b301ac22c4ce2
|
4
|
+
data.tar.gz: 878e694007c2d41a71ed940fc5f7cf9215a4ad23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48559b9d9ac0b9a5def0e60cd6ed4242d90e28a2ec617d71fb673c0fedadd4e6aee7a32a81c6db88d649d539a59df04ab8e83e8317c5bfe65f442a13929159f5
|
7
|
+
data.tar.gz: 5ff773471a48fc33e975ae314aec3519f9d7422b8526301bebf66f5328955f886bf9c9a8d0fb03838766d2321df230988108810aca80091a00a9d17079945202
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -52,12 +52,12 @@ Here is an example of what can be done in an IRB session:
|
|
52
52
|
|
53
53
|
$ irb -resgob
|
54
54
|
irb(main):001:0> esgob = Esgob::Client.new
|
55
|
-
=> #<Esgob::Client
|
55
|
+
=> #<Esgob::Client account=myacct>
|
56
56
|
irb(main):002:0> esgob.domains_slaves_list
|
57
57
|
=> {"example.com"=>"192.168.0.1", "example.uk"=>"192.168.0.1"}
|
58
58
|
irb(main):003:0> esgob.domains_slaves_list.keys
|
59
59
|
=> ["example.com", "example.uk"]
|
60
|
-
irb(main):004:0>
|
60
|
+
irb(main):004:0>
|
61
61
|
|
62
62
|
See the [API documentation] for full details.
|
63
63
|
|
data/bin/esgob
ADDED
data/esgob.gemspec
CHANGED
@@ -4,35 +4,37 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'esgob/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'esgob'
|
8
8
|
spec.version = Esgob::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
#spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
9
|
+
spec.authors = ['Nicholas Humfrey']
|
10
|
+
spec.email = ['njh@aelius.com']
|
11
|
+
spec.summary = 'Client library for talking to the Esgob anycast DNS API.'
|
12
|
+
# spec.description = 'TODO: Write a longer description. Optional.'
|
13
|
+
spec.homepage = 'http://github.com/njh/ruby-esgob'
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
|
22
|
-
spec.add_dependency
|
21
|
+
spec.add_dependency 'json', '~> 1.8'
|
22
|
+
spec.add_dependency 'thor', '~> 0.19.1'
|
23
23
|
|
24
24
|
if Gem.ruby_version > Gem::Version.new('1.9')
|
25
25
|
spec.add_development_dependency 'bundler', '>= 1.5.0'
|
26
26
|
spec.add_development_dependency 'rake', '>= 0.10.0'
|
27
27
|
spec.add_development_dependency 'yard', '>= 0.8.0'
|
28
28
|
spec.add_development_dependency 'fakeweb', '~> 1.3.0'
|
29
|
+
spec.add_development_dependency 'mocha', '~> 1.1.0'
|
29
30
|
spec.add_development_dependency 'simplecov'
|
30
31
|
elsif Gem.ruby_version > Gem::Version.new('1.8')
|
31
32
|
spec.add_development_dependency 'bundler', '>= 1.1.0'
|
32
33
|
spec.add_development_dependency 'rake', '~> 0.9.0'
|
33
34
|
spec.add_development_dependency 'yard', '~> 0.8.0'
|
34
|
-
spec.add_development_dependency 'minitest', '~> 5.5.0'
|
35
35
|
spec.add_development_dependency 'fakeweb', '~> 1.3.0'
|
36
|
+
spec.add_development_dependency 'minitest', '~> 5.5.0'
|
37
|
+
spec.add_development_dependency 'mocha', '~> 1.1.0'
|
36
38
|
else
|
37
39
|
raise "#{Gem.ruby_version} is an unsupported version of ruby"
|
38
40
|
end
|
data/lib/esgob/cli.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
class Esgob::CLI < Thor
|
4
|
+
class_option :account,
|
5
|
+
:type => :string,
|
6
|
+
:aliases => '-a',
|
7
|
+
:banner => 'Account Name'
|
8
|
+
|
9
|
+
class_option :key,
|
10
|
+
:type => :string,
|
11
|
+
:aliases => '-k',
|
12
|
+
:banner => 'API Key'
|
13
|
+
|
14
|
+
class_option :verbose,
|
15
|
+
:type => :boolean,
|
16
|
+
:default => false,
|
17
|
+
:aliases => '-v'
|
18
|
+
|
19
|
+
def self.start(args = ARGV, config = {})
|
20
|
+
config[:shell] ||= Thor::Base.shell.new
|
21
|
+
begin
|
22
|
+
super(args, config)
|
23
|
+
rescue Esgob::ServerError => err
|
24
|
+
$stderr.puts config[:shell].set_color("=> Error: #{err.message} [#{err.code}]", :red, :bold)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "account", "Display account info"
|
29
|
+
def account
|
30
|
+
client.accounts_get.each_pair do |k, v|
|
31
|
+
say sprintf("%8s: %s\n", k, v)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "domains", "List all domains"
|
36
|
+
def domains
|
37
|
+
print_table(
|
38
|
+
[['Domain', 'Type']] +
|
39
|
+
[['------', '----']] +
|
40
|
+
client.domains_list.map { |h| [h[:domain], h[:type]] }
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "slaves", "List slave domains"
|
45
|
+
def slaves
|
46
|
+
print_table(
|
47
|
+
[['Domain', 'Master IP']] +
|
48
|
+
[['------', '---------']] +
|
49
|
+
client.domains_slaves_list.to_a
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "slaves-add DOMAIN MASTERIP", "Add new slave domain"
|
54
|
+
def slaves_add(domain, masterip)
|
55
|
+
check_action do
|
56
|
+
client.domains_slaves_add(domain, masterip)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "slaves-delete DOMAIN", "Delete a slave domain"
|
61
|
+
def slaves_delete(domain)
|
62
|
+
check_action do
|
63
|
+
client.domains_slaves_delete(domain)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "slaves-transfer DOMAIN",
|
68
|
+
"Force transfer from master of a slave domain"
|
69
|
+
def slaves_transfer(domain)
|
70
|
+
check_action do
|
71
|
+
client.domains_slaves_forcetransfer(domain)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "slaves-update DOMAIN MASTERIP",
|
76
|
+
"Updates the master IP of a slave domain"
|
77
|
+
def slaves_update(domain, masterip)
|
78
|
+
check_action do
|
79
|
+
client.domains_slaves_updatemasterip(domain, masterip)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "slaves-sync FILE MASTERIP",
|
84
|
+
"Synronises list of slave domains in a file"
|
85
|
+
def slaves_sync(filename, masterip)
|
86
|
+
domains = []
|
87
|
+
File.foreach(filename) do |line|
|
88
|
+
domains << line.strip.split(/\s+/).first
|
89
|
+
end
|
90
|
+
|
91
|
+
check_action do
|
92
|
+
client.domains_slaves_sync(domains, masterip)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
desc "soacheck DOMAIN",
|
97
|
+
"Fetch domain SOA serial number for all nodes"
|
98
|
+
def soacheck(domain)
|
99
|
+
response = client.domains_tools_soacheck(domain)
|
100
|
+
print_table(
|
101
|
+
[['Identifier', 'Type', 'Country', 'SOA', 'Response']] +
|
102
|
+
[['----------', '----', '-------', '---', '--------']] +
|
103
|
+
response[:responses][:masters].map do |node|
|
104
|
+
[node[:ip], "master", '', node[:soa], node[:response]]
|
105
|
+
end +
|
106
|
+
response[:responses][:anycastnodes].map do |node|
|
107
|
+
[node[:ref], 'anycast', node[:country], node[:soa], node[:response]]
|
108
|
+
end
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
desc "version", "Show Esgob Ruby Client version"
|
113
|
+
def version
|
114
|
+
say "Esgob Ruby Client version #{Esgob::VERSION}"
|
115
|
+
end
|
116
|
+
map "--version" => "version"
|
117
|
+
|
118
|
+
private ######################################################################
|
119
|
+
|
120
|
+
def client
|
121
|
+
@client ||= Esgob::Client.new(options[:account], options[:key])
|
122
|
+
end
|
123
|
+
|
124
|
+
def check_action
|
125
|
+
results = yield
|
126
|
+
results = [results] unless results.is_a?(Array)
|
127
|
+
results.each do |result|
|
128
|
+
unless result[:action].nil?
|
129
|
+
say "#{result[:domain]} " + set_color("=> #{result[:action]}", :green, :bold)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
data/lib/esgob/client.rb
CHANGED
@@ -10,19 +10,27 @@ class Esgob::Client
|
|
10
10
|
DEFAULT_API_ENDPOINT = "https://api.esgob.com/1.0/".freeze
|
11
11
|
|
12
12
|
def initialize(*args)
|
13
|
-
if args.first.
|
14
|
-
args.first.each_pair { |k,v| send("#{k}=", v) }
|
13
|
+
if args.first.is_a?(Hash)
|
14
|
+
args.first.each_pair { |k, v| send("#{k}=", v) }
|
15
15
|
else
|
16
16
|
self.account = args[0]
|
17
17
|
self.api_key = args[1]
|
18
18
|
end
|
19
19
|
|
20
|
+
self.account ||= ENV['ESGOB_ACCOUNT']
|
21
|
+
self.api_key ||= ENV['ESGOB_API_KEY']
|
20
22
|
self.endpoint ||= DEFAULT_API_ENDPOINT
|
21
|
-
|
22
|
-
|
23
|
+
|
24
|
+
if account.nil? or account.empty?
|
25
|
+
raise(ArgumentError, "No account name configured for Esgob")
|
26
|
+
end
|
27
|
+
|
28
|
+
if api_key.nil? or api_key.empty?
|
29
|
+
raise(ArgumentError, "No API key configured for Esgob")
|
30
|
+
end
|
23
31
|
end
|
24
32
|
|
25
|
-
def call(function_name, arguments={})
|
33
|
+
def call(function_name, arguments = {})
|
26
34
|
uri = URI(endpoint + function_name)
|
27
35
|
uri.query = build_query(default_arguments.merge(arguments))
|
28
36
|
|
@@ -32,22 +40,28 @@ class Esgob::Client
|
|
32
40
|
http.request(req)
|
33
41
|
end
|
34
42
|
|
35
|
-
if res.
|
36
|
-
|
37
|
-
|
43
|
+
if res.content_type == 'application/json'
|
44
|
+
data = symbolize_keys! JSON.parse(res.body)
|
45
|
+
if data.key?(:error)
|
46
|
+
raise Esgob::ServerError.new(
|
47
|
+
data[:error][:message],
|
48
|
+
data[:error][:code].to_s
|
49
|
+
)
|
50
|
+
elsif res.code !~ /^2/
|
51
|
+
raise Esgob::ServerError.new(res.message, res.code)
|
38
52
|
else
|
39
|
-
|
53
|
+
return data
|
40
54
|
end
|
41
55
|
else
|
42
|
-
|
43
|
-
res.value
|
56
|
+
raise "HTTP response from ESGOB is not of type JSON"
|
44
57
|
end
|
45
|
-
|
46
58
|
end
|
47
59
|
|
48
60
|
# Return account status; credit balance, etc
|
49
61
|
def accounts_get
|
50
|
-
call('accounts.get')
|
62
|
+
account = call('accounts.get')
|
63
|
+
account[:added] = Time.at(account[:added]) if account[:added].is_a?(Fixnum)
|
64
|
+
account
|
51
65
|
end
|
52
66
|
|
53
67
|
# Returns all hosted domains
|
@@ -56,7 +70,7 @@ class Esgob::Client
|
|
56
70
|
end
|
57
71
|
|
58
72
|
# Returns all hosted slave domains as a hash
|
59
|
-
#
|
73
|
+
#
|
60
74
|
def domains_slaves_list
|
61
75
|
Hash[
|
62
76
|
call('domains.slaves.list')[:domains].map do |item|
|
@@ -67,32 +81,44 @@ class Esgob::Client
|
|
67
81
|
|
68
82
|
# Adds a new slave domain
|
69
83
|
def domains_slaves_add(domain, masterip)
|
70
|
-
call('domains.slaves.add', :domain => domain, :masterip => masterip)
|
84
|
+
result = call('domains.slaves.add', :domain => domain, :masterip => masterip)
|
85
|
+
result[:domain] ||= domain
|
86
|
+
result
|
71
87
|
end
|
72
88
|
|
73
89
|
# Deletes a slave domain
|
74
90
|
def domains_slaves_delete(domain)
|
75
|
-
call('domains.slaves.delete', :domain => domain)
|
91
|
+
result = call('domains.slaves.delete', :domain => domain)
|
92
|
+
result[:domain] ||= domain
|
93
|
+
result
|
76
94
|
end
|
77
95
|
|
78
96
|
# Force AXFR / transfer from master of a slave domain
|
79
97
|
def domains_slaves_forcetransfer(domain)
|
80
|
-
call('domains.slaves.forcetransfer', :domain => domain)
|
98
|
+
result = call('domains.slaves.forcetransfer', :domain => domain)
|
99
|
+
result[:domain] ||= domain
|
100
|
+
result
|
81
101
|
end
|
82
102
|
|
83
103
|
# Updates the master IP of a slave domain
|
84
104
|
def domains_slaves_updatemasterip(domain, masterip)
|
85
|
-
call('domains.slaves.updatemasterip', :domain => domain, :masterip => masterip)
|
105
|
+
result = call('domains.slaves.updatemasterip', :domain => domain, :masterip => masterip)
|
106
|
+
result[:domain] ||= domain
|
107
|
+
result
|
86
108
|
end
|
87
109
|
|
88
110
|
# Add a host allowed to AXFR out
|
89
111
|
def domains_slaves_axfrout_add(domain, axfrip)
|
90
|
-
call('domains.slaves.axfrout.add', :domain => domain, :axfrip => axfrip)
|
112
|
+
result = call('domains.slaves.axfrout.add', :domain => domain, :axfrip => axfrip)
|
113
|
+
result[:domain] ||= domain
|
114
|
+
result
|
91
115
|
end
|
92
116
|
|
93
117
|
# Account Delete a host allowed to AXFR out
|
94
118
|
def domains_slaves_axfrout_delete(domain, axfrip)
|
95
|
-
call('domains.slaves.axfrout.delete', :domain => domain, :axfrip => axfrip)
|
119
|
+
result = call('domains.slaves.axfrout.delete', :domain => domain, :axfrip => axfrip)
|
120
|
+
result[:domain] ||= domain
|
121
|
+
result
|
96
122
|
end
|
97
123
|
|
98
124
|
# Retrieve the domain SOA serial number from the master and each anycast node
|
@@ -100,6 +126,44 @@ class Esgob::Client
|
|
100
126
|
call('domains.tools.soacheck', :domain => domain)
|
101
127
|
end
|
102
128
|
|
129
|
+
# Given a list of domains and a master IP, add and delete domains
|
130
|
+
# so that the Esgob account matches the local list
|
131
|
+
def domains_slaves_sync(domains, masterip)
|
132
|
+
existing_domains = domains_slaves_list
|
133
|
+
|
134
|
+
# Add any missing domains
|
135
|
+
responses = []
|
136
|
+
domains.each do |domain|
|
137
|
+
unless existing_domains.include?(domain)
|
138
|
+
response = domains_slaves_add(domain, masterip)
|
139
|
+
response[:domain] ||= domain
|
140
|
+
responses << response
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Now check the existing domains
|
145
|
+
existing_domains.keys.sort.each do |domain|
|
146
|
+
if domains.include?(domain)
|
147
|
+
# Update the masterip if it isn't correct
|
148
|
+
if existing_domains[domain] != masterip
|
149
|
+
response = domains_slaves_updatemasterip(domain, masterip)
|
150
|
+
response[:domain] ||= domain
|
151
|
+
responses << response
|
152
|
+
end
|
153
|
+
else
|
154
|
+
# Delete domain; not on list
|
155
|
+
response = domains_slaves_delete(domain)
|
156
|
+
response[:domain] ||= domain
|
157
|
+
responses << response
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
responses
|
162
|
+
end
|
163
|
+
|
164
|
+
def inspect
|
165
|
+
"\#<#{self.class} account=#{@account}>"
|
166
|
+
end
|
103
167
|
|
104
168
|
protected
|
105
169
|
|
@@ -111,10 +175,10 @@ class Esgob::Client
|
|
111
175
|
when Hash
|
112
176
|
symbolize_keys!(hash[ks])
|
113
177
|
when Array
|
114
|
-
hash[ks].each {|item| symbolize_keys!(item) if item.
|
178
|
+
hash[ks].each { |item| symbolize_keys!(item) if item.is_a?(Hash) }
|
115
179
|
end
|
116
180
|
end
|
117
|
-
|
181
|
+
hash
|
118
182
|
end
|
119
183
|
|
120
184
|
def default_arguments
|
@@ -126,8 +190,8 @@ class Esgob::Client
|
|
126
190
|
end
|
127
191
|
|
128
192
|
def build_query(hash)
|
129
|
-
hash.keys.sort{|a,b| a.to_s <=> b.to_s}.map
|
130
|
-
URI
|
131
|
-
|
193
|
+
hash.keys.sort { |a, b| a.to_s <=> b.to_s }.map do |key|
|
194
|
+
URI.escape(key.to_s) + '=' + URI.escape(hash[key].to_s)
|
195
|
+
end.join('&')
|
132
196
|
end
|
133
197
|
end
|
data/lib/esgob/version.rb
CHANGED
data/lib/esgob.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
module Esgob
|
2
2
|
autoload :Client, 'esgob/client'
|
3
|
-
autoload :
|
3
|
+
autoload :CLI, 'esgob/cli'
|
4
|
+
autoload :VERSION, 'esgob/version'
|
5
|
+
|
6
|
+
class ServerError < StandardError
|
7
|
+
attr_reader :code
|
8
|
+
|
9
|
+
def initialize(message, code = nil)
|
10
|
+
super message
|
11
|
+
@code = code
|
12
|
+
end
|
13
|
+
end
|
4
14
|
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'esgob'
|
5
|
+
|
6
|
+
class TestCLI < MiniTest::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
# Run before each test
|
9
|
+
FakeWeb.clean_registry
|
10
|
+
|
11
|
+
@client = Esgob::Client.new('acct', 'xxxx')
|
12
|
+
Esgob::Client.stubs(:new).returns(@client)
|
13
|
+
|
14
|
+
ENV['THOR_SHELL'] = 'Basic'
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
# Reset environment variables after each test
|
19
|
+
ENV.delete('ESGOB_ACCOUNT')
|
20
|
+
ENV.delete('ESGOB_API_KEY')
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_account
|
24
|
+
register_fixture('accounts.get')
|
25
|
+
|
26
|
+
output = capture(:stdout) { Esgob::CLI.start(%w(account)) }
|
27
|
+
assert_match " id: xyz\n", output
|
28
|
+
assert_match " name: Person Name\n", output
|
29
|
+
assert_match " credits: 48\n", output
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_account_error
|
33
|
+
FakeWeb.register_uri(
|
34
|
+
:get, %r{^https?://api\.esgob\.com(:443)?/},
|
35
|
+
:status => ['401', 'UNAUTHORIZED'],
|
36
|
+
:content_type => 'application/json',
|
37
|
+
:body => read_fixture(:code_1003)
|
38
|
+
)
|
39
|
+
|
40
|
+
output = capture(:stderr) { Esgob::CLI.start(%w(account)) }
|
41
|
+
assert_equal "=> Error: Account and API key combination not valid [1003]\n", output
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_domains
|
45
|
+
register_fixture('domains.list')
|
46
|
+
|
47
|
+
output = capture(:stdout) { Esgob::CLI.start(%w(domains)) }
|
48
|
+
assert_match "Domain Type\n", output
|
49
|
+
assert_match "------ ----\n", output
|
50
|
+
assert_match "example.com slave\n", output
|
51
|
+
assert_match "example.uk slave\n", output
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_slaves
|
55
|
+
register_fixture('domains.slaves.list')
|
56
|
+
|
57
|
+
output = capture(:stdout) { Esgob::CLI.start(%w(slaves)) }
|
58
|
+
assert_match "Domain Master IP\n", output
|
59
|
+
assert_match "------ ---------\n", output
|
60
|
+
assert_match "example.com 195.177.253.166\n", output
|
61
|
+
assert_match "example.uk 195.177.253.166\n", output
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_slaves_add
|
65
|
+
register_fixture('domains.slaves.add')
|
66
|
+
|
67
|
+
output = capture(:stdout) { Esgob::CLI.start(%w(slaves-add example.org 195.177.253.166)) }
|
68
|
+
assert_equal "example.org => domain added\n", output
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_slaves_delete
|
72
|
+
register_fixture('domains.slaves.delete')
|
73
|
+
|
74
|
+
output = capture(:stdout) { Esgob::CLI.start(%w(slaves-delete example.org)) }
|
75
|
+
assert_equal "example.org => domain deleted\n", output
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_slaves_delete_error
|
79
|
+
FakeWeb.register_uri(
|
80
|
+
:get, %r{^https?://api\.esgob\.com(:443)?/},
|
81
|
+
:status => ['403', 'FORBIDDEN'],
|
82
|
+
:content_type => 'application/json',
|
83
|
+
:body => read_fixture(:code_2007)
|
84
|
+
)
|
85
|
+
|
86
|
+
output = capture(:stderr) { Esgob::CLI.start(%w(slaves-delete example.com)) }
|
87
|
+
assert_equal "=> Error: Domain is not present in your account [2007]\n", output
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_slaves_transfer
|
91
|
+
register_fixture('domains.slaves.forcetransfer')
|
92
|
+
|
93
|
+
output = capture(:stdout) { Esgob::CLI.start(%w(slaves-transfer example.org)) }
|
94
|
+
assert_equal "example.org => Domain AXFR requested from master\n", output
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_slaves_update
|
98
|
+
register_fixture('domains.slaves.updatemasterip')
|
99
|
+
|
100
|
+
output = capture(:stdout) { Esgob::CLI.start(%w(slaves-update example.org 195.177.253.167)) }
|
101
|
+
assert_equal "example.org => domain master IP updated\n", output
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_slaves_sync
|
105
|
+
@client.expects(:domains_slaves_list).with().returns('a.com' => '195.177.253.169', 'b.com' => '195.177.253.169')
|
106
|
+
@client.expects(:domains_slaves_delete).with('a.com').returns(:action => 'domain deleted')
|
107
|
+
@client.expects(:domains_slaves_add).with('c.com', '195.177.253.169').returns(:action => 'domain added')
|
108
|
+
|
109
|
+
output = capture(:stdout) { Esgob::CLI.start(['slaves-sync', fixture_path('sync-domain-list.txt'), '195.177.253.169']) }
|
110
|
+
assert_match "a.com => domain deleted\n", output
|
111
|
+
assert_match "c.com => domain added\n", output
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_soacheck
|
115
|
+
register_fixture('domains.tools.soacheck')
|
116
|
+
|
117
|
+
output = capture(:stdout) { Esgob::CLI.start(%w(soacheck example.org)) }
|
118
|
+
assert_match "Identifier Type Country SOA Response\n", output
|
119
|
+
assert_match "---------- ---- ------- --- --------\n", output
|
120
|
+
assert_match "195.177.253.167 master fail\n", output
|
121
|
+
assert_match "4f31ad80 anycast gb fail\n", output
|
122
|
+
assert_match "fgej72a1 anycast us fail\n", output
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_version
|
126
|
+
assert_match /Esgob Ruby Client version \d+.\d+\.\d+/,
|
127
|
+
capture(:stdout) { Esgob::CLI.start(%w(version)) }
|
128
|
+
end
|
129
|
+
end
|
data/test/esgob_client_test.rb
CHANGED
@@ -44,6 +44,20 @@ class TestClient < MiniTest::Unit::TestCase
|
|
44
44
|
assert_equal 'http://api.example.com/', client.endpoint
|
45
45
|
end
|
46
46
|
|
47
|
+
def test_new_client_with_no_account
|
48
|
+
ENV.delete('ESGOB_ACCOUNT')
|
49
|
+
assert_raises(ArgumentError) do
|
50
|
+
Esgob::Client.new(nil, 'mykey')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_new_client_with_no_api_key
|
55
|
+
ENV.delete('ESGOB_API_KEY')
|
56
|
+
assert_raises(ArgumentError) do
|
57
|
+
Esgob::Client.new('acct', nil)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
47
61
|
def test_call_with_no_parameters
|
48
62
|
register_fixture('accounts.get')
|
49
63
|
response = @client.call('accounts.get')
|
@@ -53,7 +67,13 @@ class TestClient < MiniTest::Unit::TestCase
|
|
53
67
|
FakeWeb.last_request.path
|
54
68
|
)
|
55
69
|
assert_equal(
|
56
|
-
{
|
70
|
+
{
|
71
|
+
:credits => 48,
|
72
|
+
:users => [],
|
73
|
+
:added => 1422792434,
|
74
|
+
:id => 'xyz',
|
75
|
+
:name => 'Person Name'
|
76
|
+
},
|
57
77
|
response
|
58
78
|
)
|
59
79
|
end
|
@@ -79,27 +99,38 @@ class TestClient < MiniTest::Unit::TestCase
|
|
79
99
|
end
|
80
100
|
|
81
101
|
def test_call_with_404_error
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
102
|
+
FakeWeb.register_uri(
|
103
|
+
:get, %r{^https?://api\.esgob\.com(:443)?/},
|
104
|
+
:status => ['404', 'Not Found'],
|
105
|
+
:content_type => 'application/json',
|
106
|
+
:body => '{}'
|
107
|
+
)
|
108
|
+
err = assert_raises(Esgob::ServerError) { @client.call('accounts.get') }
|
109
|
+
assert_equal 'Not Found', err.message
|
110
|
+
assert_equal '404', err.code
|
91
111
|
end
|
92
112
|
|
93
113
|
def test_call_with_non_json_reponse
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
114
|
+
FakeWeb.register_uri(
|
115
|
+
:get, %r{^https?://api\.esgob\.com(:443)?/},
|
116
|
+
:status => ['200', 'OK'],
|
117
|
+
:content_type => 'text/plain',
|
118
|
+
:body => 'This is plain text'
|
119
|
+
)
|
120
|
+
err = assert_raises(RuntimeError) { @client.call('accounts.get') }
|
121
|
+
assert_equal 'HTTP response from ESGOB is not of type JSON', err.message
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_call_domain_not_present
|
125
|
+
FakeWeb.register_uri(
|
126
|
+
:get, %r{^https?://api\.esgob\.com(:443)?/},
|
127
|
+
:status => ['403', 'FORBIDDEN'],
|
128
|
+
:content_type => 'application/json',
|
129
|
+
:body => read_fixture(:code_2007)
|
130
|
+
)
|
131
|
+
err = assert_raises(Esgob::ServerError) { @client.call('domains.slaves.delete', :domain => 'example.org') }
|
132
|
+
assert_equal 'Domain is not present in your account', err.message
|
133
|
+
assert_equal '2007', err.code
|
103
134
|
end
|
104
135
|
|
105
136
|
def test_accounts_get
|
@@ -111,7 +142,13 @@ class TestClient < MiniTest::Unit::TestCase
|
|
111
142
|
FakeWeb.last_request.path
|
112
143
|
)
|
113
144
|
assert_equal(
|
114
|
-
{
|
145
|
+
{
|
146
|
+
:credits => 48,
|
147
|
+
:users => [],
|
148
|
+
:added => Time.parse('2015-02-01 12:07:14 +0000'),
|
149
|
+
:id => 'xyz',
|
150
|
+
:name => 'Person Name'
|
151
|
+
},
|
115
152
|
response
|
116
153
|
)
|
117
154
|
end
|
@@ -126,8 +163,8 @@ class TestClient < MiniTest::Unit::TestCase
|
|
126
163
|
)
|
127
164
|
assert_equal(
|
128
165
|
[
|
129
|
-
{:domain =>
|
130
|
-
{:domain =>
|
166
|
+
{ :domain => 'example.com', :type => 'slave' },
|
167
|
+
{ :domain => 'example.uk', :type => 'slave' }
|
131
168
|
],
|
132
169
|
response
|
133
170
|
)
|
@@ -142,7 +179,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
142
179
|
FakeWeb.last_request.path
|
143
180
|
)
|
144
181
|
assert_equal(
|
145
|
-
{
|
182
|
+
{ 'example.com' => '195.177.253.166', 'example.uk' => '195.177.253.166' },
|
146
183
|
response
|
147
184
|
)
|
148
185
|
end
|
@@ -155,7 +192,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
155
192
|
'/1.0/domains.slaves.add?account=acct&domain=example.org&f=json&key=xxxx&masterip=195.177.253.166',
|
156
193
|
FakeWeb.last_request.path
|
157
194
|
)
|
158
|
-
assert_equal({:action=>
|
195
|
+
assert_equal({ :action => 'domain added', :domain => 'example.org' }, response)
|
159
196
|
end
|
160
197
|
|
161
198
|
def test_domains_slaves_delete
|
@@ -166,7 +203,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
166
203
|
'/1.0/domains.slaves.delete?account=acct&domain=example.org&f=json&key=xxxx',
|
167
204
|
FakeWeb.last_request.path
|
168
205
|
)
|
169
|
-
assert_equal({:action=>
|
206
|
+
assert_equal({ :action => 'domain deleted', :domain => 'example.org' }, response)
|
170
207
|
end
|
171
208
|
|
172
209
|
def test_domains_slaves_forcetransfer
|
@@ -177,7 +214,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
177
214
|
'/1.0/domains.slaves.forcetransfer?account=acct&domain=example.org&f=json&key=xxxx',
|
178
215
|
FakeWeb.last_request.path
|
179
216
|
)
|
180
|
-
assert_equal({:action=>
|
217
|
+
assert_equal({ :action => 'Domain AXFR requested from master', :domain => 'example.org' }, response)
|
181
218
|
end
|
182
219
|
|
183
220
|
def test_domains_slaves_updatemasterip
|
@@ -188,7 +225,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
188
225
|
'/1.0/domains.slaves.updatemasterip?account=acct&domain=example.org&f=json&key=xxxx&masterip=195.177.253.167',
|
189
226
|
FakeWeb.last_request.path
|
190
227
|
)
|
191
|
-
assert_equal({:action=>
|
228
|
+
assert_equal({ :action => 'domain master IP updated', :domain => 'example.org' }, response)
|
192
229
|
end
|
193
230
|
|
194
231
|
def test_domains_slaves_axfrout_add
|
@@ -199,7 +236,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
199
236
|
'/1.0/domains.slaves.axfrout.add?account=acct&axfrip=195.177.253.1&domain=example.org&f=json&key=xxxx',
|
200
237
|
FakeWeb.last_request.path
|
201
238
|
)
|
202
|
-
assert_equal({:action=>
|
239
|
+
assert_equal({ :action => 'domain AXFR out IPs updated', :domain => 'example.org' }, response)
|
203
240
|
end
|
204
241
|
|
205
242
|
def test_domains_slaves_axfrout_delete
|
@@ -210,7 +247,7 @@ class TestClient < MiniTest::Unit::TestCase
|
|
210
247
|
'/1.0/domains.slaves.axfrout.delete?account=acct&axfrip=195.177.253.1&domain=example.org&f=json&key=xxxx',
|
211
248
|
FakeWeb.last_request.path
|
212
249
|
)
|
213
|
-
assert_equal({:action=>
|
250
|
+
assert_equal({ :action => 'domain AXFR out IPs updated', :domain => 'example.org' }, response)
|
214
251
|
end
|
215
252
|
|
216
253
|
def test_domains_tools_soacheck
|
@@ -225,4 +262,56 @@ class TestClient < MiniTest::Unit::TestCase
|
|
225
262
|
refute_empty(response[:responses])
|
226
263
|
end
|
227
264
|
|
265
|
+
def test_domains_slaves_sync_noop
|
266
|
+
@client.expects(:domains_slaves_list).with().returns(
|
267
|
+
'a.com' => '195.177.253.1', 'b.com' => '195.177.253.1'
|
268
|
+
)
|
269
|
+
|
270
|
+
responses = @client.domains_slaves_sync(['a.com', 'b.com'], '195.177.253.1')
|
271
|
+
assert_equal [], responses
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_domains_slaves_sync_add_only
|
275
|
+
@client.expects(:domains_slaves_list).with().returns({})
|
276
|
+
@client.expects(:domains_slaves_add).with('a.com', '195.177.253.1').returns(:action => 'domain added')
|
277
|
+
@client.expects(:domains_slaves_add).with('b.com', '195.177.253.1').returns(:action => 'domain added')
|
278
|
+
|
279
|
+
responses = @client.domains_slaves_sync(['a.com', 'b.com'], '195.177.253.1')
|
280
|
+
assert_equal [
|
281
|
+
{ :action => 'domain added', :domain => 'a.com' },
|
282
|
+
{ :action => 'domain added', :domain => 'b.com' }
|
283
|
+
], responses
|
284
|
+
end
|
285
|
+
|
286
|
+
def test_domains_slaves_sync_add_and_delete
|
287
|
+
@client.expects(:domains_slaves_list).with().returns({'a.com' => '195.177.253.1'})
|
288
|
+
@client.expects(:domains_slaves_delete).with('a.com').returns({:action => 'domain deleted'})
|
289
|
+
@client.expects(:domains_slaves_add).with('b.com', '195.177.253.1').returns(:action => 'domain added')
|
290
|
+
|
291
|
+
responses = @client.domains_slaves_sync(['b.com'], '195.177.253.1')
|
292
|
+
assert_equal [
|
293
|
+
{ :action => 'domain added', :domain => 'b.com' },
|
294
|
+
{ :action => 'domain deleted', :domain => 'a.com' }
|
295
|
+
], responses
|
296
|
+
end
|
297
|
+
|
298
|
+
def test_domains_slaves_sync_add_and_delete_and_change_masterip
|
299
|
+
@client.expects(:domains_slaves_list).with().returns(
|
300
|
+
'a.com' => '195.177.253.1', 'c.com' => '127.0.0.1'
|
301
|
+
)
|
302
|
+
@client.expects(:domains_slaves_delete).with('a.com').returns(:action => 'domain deleted')
|
303
|
+
@client.expects(:domains_slaves_add).with('b.com', '195.177.253.1').returns(:action => 'domain added')
|
304
|
+
@client.expects(:domains_slaves_updatemasterip).with('c.com', '195.177.253.1').returns(:action => 'domain master IP updated')
|
305
|
+
|
306
|
+
responses = @client.domains_slaves_sync(['b.com', 'c.com'], '195.177.253.1')
|
307
|
+
assert_equal [
|
308
|
+
{ :action => 'domain added', :domain => 'b.com' },
|
309
|
+
{ :action => 'domain deleted', :domain => 'a.com' },
|
310
|
+
{ :action => 'domain master IP updated', :domain => 'c.com' }
|
311
|
+
], responses
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_inspect
|
315
|
+
assert_match('#<Esgob::Client account=acct>', @client.inspect)
|
316
|
+
end
|
228
317
|
end
|
data/test/esgob_version_test.rb
CHANGED
@@ -4,11 +4,9 @@ require 'test_helper'
|
|
4
4
|
require 'esgob'
|
5
5
|
|
6
6
|
class TestVersion < MiniTest::Unit::TestCase
|
7
|
-
|
8
7
|
def test_version_number_looks_sensible
|
9
8
|
assert_equal 'constant', defined?(Esgob::VERSION)
|
10
9
|
assert_kind_of String, Esgob::VERSION
|
11
10
|
assert_match /^\d{1,2}\.\d{1,2}\.\d{1,2}$/, Esgob::VERSION
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
data/test/test_helper.rb
CHANGED
@@ -4,6 +4,7 @@ require 'rubygems'
|
|
4
4
|
require 'bundler'
|
5
5
|
Bundler.require(:default, :development)
|
6
6
|
require 'minitest/autorun'
|
7
|
+
require 'mocha/mini_test'
|
7
8
|
|
8
9
|
unless RUBY_VERSION =~ /^1\.8/
|
9
10
|
SimpleCov.start
|
@@ -11,18 +12,34 @@ end
|
|
11
12
|
|
12
13
|
FakeWeb.allow_net_connect = false
|
13
14
|
|
15
|
+
def fixture_path(fixture_name)
|
16
|
+
fixture_name = fixture_name.to_s
|
17
|
+
fixture_name += '.json' unless fixture_name.match(/\.\w+$/)
|
18
|
+
File.join(File.dirname(__FILE__), 'fixtures', fixture_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_fixture(fixture_name)
|
22
|
+
File.read fixture_path(fixture_name)
|
23
|
+
end
|
14
24
|
|
15
|
-
def register_fixture(api_call, fixture_name=nil)
|
25
|
+
def register_fixture(api_call, fixture_name = nil)
|
16
26
|
if fixture_name.nil?
|
17
27
|
fixture_name = api_call.gsub(/\W+/, '_')
|
18
28
|
end
|
19
29
|
|
20
|
-
fixture_file = File.join(File.dirname(__FILE__), 'fixtures', fixture_name + '.json')
|
21
|
-
|
22
30
|
FakeWeb.register_uri(
|
23
31
|
:get, %r[^https?://api\.esgob\.com(:443)?/1.0/#{api_call}],
|
24
32
|
:status => ["200", "OK"],
|
25
33
|
:content_type => "application/json",
|
26
|
-
:body =>
|
34
|
+
:body => read_fixture(fixture_name)
|
27
35
|
)
|
28
36
|
end
|
37
|
+
|
38
|
+
def capture(stream)
|
39
|
+
original = eval "$#{stream}"
|
40
|
+
eval "$#{stream} = StringIO.new"
|
41
|
+
yield
|
42
|
+
result = eval("$#{stream}").string
|
43
|
+
eval "$#{stream} = original"
|
44
|
+
result
|
45
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: esgob
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas Humfrey
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.19.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.19.1
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,20 @@ dependencies:
|
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: 1.3.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mocha
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.1.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.1.0
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: simplecov
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,7 +125,8 @@ dependencies:
|
|
97
125
|
description:
|
98
126
|
email:
|
99
127
|
- njh@aelius.com
|
100
|
-
executables:
|
128
|
+
executables:
|
129
|
+
- esgob
|
101
130
|
extensions: []
|
102
131
|
extra_rdoc_files: []
|
103
132
|
files:
|
@@ -107,13 +136,18 @@ files:
|
|
107
136
|
- LICENSE.md
|
108
137
|
- README.md
|
109
138
|
- Rakefile
|
139
|
+
- bin/esgob
|
110
140
|
- esgob.gemspec
|
111
141
|
- lib/esgob.rb
|
142
|
+
- lib/esgob/cli.rb
|
112
143
|
- lib/esgob/client.rb
|
113
144
|
- lib/esgob/version.rb
|
145
|
+
- test/esgob_cli_test.rb
|
114
146
|
- test/esgob_client_test.rb
|
115
147
|
- test/esgob_version_test.rb
|
116
148
|
- test/fixtures/accounts_get.json
|
149
|
+
- test/fixtures/code_1003.json
|
150
|
+
- test/fixtures/code_2007.json
|
117
151
|
- test/fixtures/domains_list.json
|
118
152
|
- test/fixtures/domains_slaves_add.json
|
119
153
|
- test/fixtures/domains_slaves_axfrout_add.json
|
@@ -123,8 +157,9 @@ files:
|
|
123
157
|
- test/fixtures/domains_slaves_list.json
|
124
158
|
- test/fixtures/domains_slaves_updatemasterip.json
|
125
159
|
- test/fixtures/domains_tools_soacheck.json
|
160
|
+
- test/fixtures/sync-domain-list.txt
|
126
161
|
- test/test_helper.rb
|
127
|
-
homepage:
|
162
|
+
homepage: http://github.com/njh/ruby-esgob
|
128
163
|
licenses:
|
129
164
|
- MIT
|
130
165
|
metadata: {}
|
@@ -149,9 +184,12 @@ signing_key:
|
|
149
184
|
specification_version: 4
|
150
185
|
summary: Client library for talking to the Esgob anycast DNS API.
|
151
186
|
test_files:
|
187
|
+
- test/esgob_cli_test.rb
|
152
188
|
- test/esgob_client_test.rb
|
153
189
|
- test/esgob_version_test.rb
|
154
190
|
- test/fixtures/accounts_get.json
|
191
|
+
- test/fixtures/code_1003.json
|
192
|
+
- test/fixtures/code_2007.json
|
155
193
|
- test/fixtures/domains_list.json
|
156
194
|
- test/fixtures/domains_slaves_add.json
|
157
195
|
- test/fixtures/domains_slaves_axfrout_add.json
|
@@ -161,5 +199,6 @@ test_files:
|
|
161
199
|
- test/fixtures/domains_slaves_list.json
|
162
200
|
- test/fixtures/domains_slaves_updatemasterip.json
|
163
201
|
- test/fixtures/domains_tools_soacheck.json
|
202
|
+
- test/fixtures/sync-domain-list.txt
|
164
203
|
- test/test_helper.rb
|
165
204
|
has_rdoc:
|