esgob 0.0.2 → 0.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f029cb699d12ea2f9ebc3d62538b301ac22c4ce2
4
- data.tar.gz: 878e694007c2d41a71ed940fc5f7cf9215a4ad23
3
+ metadata.gz: 3f360864b7199c78e7842d5792c7557cbbead80e
4
+ data.tar.gz: ff27595eaf87037c471f87193e9cf4e71075dc94
5
5
  SHA512:
6
- metadata.gz: 48559b9d9ac0b9a5def0e60cd6ed4242d90e28a2ec617d71fb673c0fedadd4e6aee7a32a81c6db88d649d539a59df04ab8e83e8317c5bfe65f442a13929159f5
7
- data.tar.gz: 5ff773471a48fc33e975ae314aec3519f9d7422b8526301bebf66f5328955f886bf9c9a8d0fb03838766d2321df230988108810aca80091a00a9d17079945202
6
+ metadata.gz: a731e04c8c2d50199ad8222f36773ecb5c223455a4dc0c039c5bd50a41ba709a6cae4c744d663430447cee26c5d09257c5e56a3ac1d8cb4b01784593b165af06
7
+ data.tar.gz: 6203a00e25e0b844c92814de5f093e569ac6bd2fb0f21cd2c75fe3bf7132729c96c4674dd22623b8efe37e5c6813ae039c088808fe533b971433cda05927e43b
data/README.md CHANGED
@@ -5,12 +5,17 @@ Esgob Ruby Client
5
5
 
6
6
  [Esgob Ltd] operate an [international network] of anycast servers.
7
7
  Their [Secondary DNS] service is available for free.
8
- This Ruby Gem provides convenient access to the [Esgob API].
8
+ This Ruby Gem provides convenient access to the [Esgob API] via a command line tool
9
+ and Ruby library.
9
10
 
10
11
 
11
12
  ## Installation
12
13
 
13
- Add this line to your application's Gemfile:
14
+ Install it as a gem using:
15
+
16
+ $ gem install esgob
17
+
18
+ Or add this line to your application's Gemfile:
14
19
 
15
20
  ```ruby
16
21
  gem 'esgob'
@@ -20,20 +25,66 @@ And then execute:
20
25
 
21
26
  $ bundle
22
27
 
23
- Or install it yourself as:
24
28
 
25
- $ gem install esgob
29
+ ## Command Line Usage
30
+
31
+ Without any arguments, the ```esgob``` tool will display a list of commands:
32
+
33
+ ```
34
+ Commands:
35
+ esgob account # Display account info
36
+ esgob config # Save the Esgob account and key
37
+ esgob domains # List all domains
38
+ esgob help [COMMAND] # Describe available commands or one specific command
39
+ esgob slaves # List slave domains
40
+ esgob slaves-add DOMAIN MASTERIP # Add new slave domain
41
+ esgob slaves-delete DOMAIN # Delete a slave domain
42
+ esgob slaves-sync FILE MASTERIP # Synronises list of slave domains in a file
43
+ esgob slaves-transfer DOMAIN # Force transfer from master of a slave domain
44
+ esgob slaves-update DOMAIN MASTERIP # Updates the master IP of a slave domain
45
+ esgob soacheck DOMAIN # Fetch domain SOA serial number for all nodes
46
+ esgob version # Show Esgob Ruby Client version
47
+
48
+ Options:
49
+ -a, [--account=Account Name]
50
+ -k, [--key=API Key]
51
+ -v, [--verbose], [--no-verbose]
52
+ ```
53
+
54
+ To configure the client with some credentials use the ```esgob config``` command:
26
55
 
27
- ## Usage
56
+ ```
57
+ $ esgob config
58
+ What is your Esgob account name? accountname
59
+ What is your Esgob key? 4472ed80e0f511e4aee13c0754043581
60
+ Configuration written to /home/username/.esgob
61
+ ```
62
+
63
+
64
+
65
+ ## Library Usage
28
66
 
29
67
  First create a new client instance, by passing in your account name and API key:
30
68
 
31
69
  esgob = Esgob::Client.new('account', 'key')
32
70
 
33
- Alternatively, as it is often desirable to keep secrets outside of the source code, it is also possible to pass in the account name and API key using environment variables set in the shell:
71
+ Alternatively, as it is often desirable to keep secrets outside of the source code,
72
+ it is also possible to pass in the account name and API key using a configuration file.
73
+ The following paths are searched in the following order:
74
+
75
+ ~/.esgob
76
+ /usr/local/etc/esgob.conf
77
+ /etc/esgob.conf
78
+
79
+ The configuration file should be in the format:
80
+
81
+ account some_account_name
82
+ key kskjhdkjdhkjhdkjdhdkjhdkjhd
83
+
84
+ Or set using environment variables:
34
85
 
35
86
  export ESGOB_ACCOUNT=accountname
36
- export ESGOB_API_KEY=4472ed80e0f511e4aee13c0754043581
87
+ export ESGOB_KEY=4472ed80e0f511e4aee13c0754043581
37
88
 
38
89
  The client instance can then be initialised without passing any arguments:
39
90
 
@@ -1,9 +1,12 @@
1
1
  module Esgob
2
2
  autoload :Client, 'esgob/client'
3
+ autoload :Config, 'esgob/config'
3
4
  autoload :CLI, 'esgob/cli'
4
5
  autoload :VERSION, 'esgob/version'
5
6
 
7
+ # Exception raised when the Esgob API returns an error
6
8
  class ServerError < StandardError
9
+ # Get the error code number returned by Esgob
7
10
  attr_reader :code
8
11
 
9
12
  def initialize(message, code = nil)
@@ -11,4 +14,7 @@ module Esgob
11
14
  @code = code
12
15
  end
13
16
  end
17
+
18
+ # Exception raised if client is configured
19
+ class UnconfiguredError < StandardError; end
14
20
  end
@@ -22,16 +22,28 @@ class Esgob::CLI < Thor
22
22
  super(args, config)
23
23
  rescue Esgob::ServerError => err
24
24
  $stderr.puts config[:shell].set_color("=> Error: #{err.message} [#{err.code}]", :red, :bold)
25
+ rescue Esgob::UnconfiguredError => err
26
+ $stderr.puts config[:shell].set_color("=> Error: #{err.message}", :red, :bold)
27
+ $stderr.puts "Use the 'esgob config' command to create a configuration file."
25
28
  end
26
29
  end
27
30
 
31
+ desc "config", "Save the Esgob account and key"
32
+ def config
33
+ config = Esgob::Config.new
34
+ config.account = ask("What is your Esgob account name?")
35
+ config.key = ask("What is your Esgob key?")
36
+ config.save
37
+ say "Configuration written to #{config.filepath}"
38
+ end
39
+
28
40
  desc "account", "Display account info"
29
41
  def account
30
42
  client.accounts_get.each_pair do |k, v|
31
43
  say sprintf("%8s: %s\n", k, v)
32
44
  end
33
45
  end
34
-
46
+
35
47
  desc "domains", "List all domains"
36
48
  def domains
37
49
  print_table(
@@ -118,7 +130,11 @@ class Esgob::CLI < Thor
118
130
  private ######################################################################
119
131
 
120
132
  def client
121
- @client ||= Esgob::Client.new(options[:account], options[:key])
133
+ @client ||= if options[:account] and options[:key]
134
+ Esgob::Client.new(options[:account], options[:key])
135
+ else
136
+ Esgob::Client.new
137
+ end
122
138
  end
123
139
 
124
140
  def check_action
@@ -130,5 +146,5 @@ class Esgob::CLI < Thor
130
146
  end
131
147
  end
132
148
  end
133
-
149
+
134
150
  end
@@ -3,36 +3,64 @@ require "uri"
3
3
  require "json"
4
4
 
5
5
  class Esgob::Client
6
- attr_accessor :endpoint
7
- attr_accessor :account
8
- attr_accessor :api_key
9
-
10
- DEFAULT_API_ENDPOINT = "https://api.esgob.com/1.0/".freeze
6
+ # Esgob configuration, used to store account name and key
7
+ # @return [Esgob::Config]
8
+ attr_reader :config
11
9
 
10
+ # Create a new Esgob Client instance.
11
+ #
12
+ # @overload initialize
13
+ # Create a new client, using one of the default configuration files.
14
+ # Or the ESGOB_ACCOUNT and ESGOB_KEY environment variables.
15
+ # @overload initialize(account, key)
16
+ # @param [String] account
17
+ # @param [String] key
18
+ # @overload initialize(args)
19
+ # @param [Hash] options
20
+ # @option options [String] :endpoint The URI of the API endpoint
21
+ # @option options [String] :account The account name
22
+ # @option options [String] :key The API key
23
+ # @overload initialize(config)
24
+ # @param [Esgob::Config] config
25
+ # @return [Esgob::Client] A new client instance.
26
+ # @example
27
+ # client = Esgob::Client.new('account', 'key')
12
28
  def initialize(*args)
13
- if args.first.is_a?(Hash)
14
- args.first.each_pair { |k, v| send("#{k}=", v) }
29
+ if args.empty?
30
+ # Load configuration from file if no arguments were given
31
+ @config = Esgob::Config.load
32
+ elsif args.first.is_a?(Esgob::Config)
33
+ @config = args.first
34
+ elsif args.first.is_a?(Hash)
35
+ @config = Esgob::Config.new(args.first)
36
+ elsif args.length == 2
37
+ @config = Esgob::Config.new(:account => args[0], :key => args[1])
15
38
  else
16
- self.account = args[0]
17
- self.api_key = args[1]
39
+ raise(ArgumentError, "Unsupported arguments for creating Esgob::Client")
18
40
  end
19
41
 
20
- self.account ||= ENV['ESGOB_ACCOUNT']
21
- self.api_key ||= ENV['ESGOB_API_KEY']
22
- self.endpoint ||= DEFAULT_API_ENDPOINT
42
+ if config.nil?
43
+ raise(Esgob::UnconfiguredError, "Unable to load Esgob configuration")
44
+ end
23
45
 
24
- if account.nil? or account.empty?
46
+ if config.account.nil? or config.account.empty?
25
47
  raise(ArgumentError, "No account name configured for Esgob")
26
48
  end
27
49
 
28
- if api_key.nil? or api_key.empty?
50
+ if config.key.nil? or config.key.empty?
29
51
  raise(ArgumentError, "No API key configured for Esgob")
30
52
  end
31
53
  end
32
54
 
33
- def call(function_name, arguments = {})
34
- uri = URI(endpoint + function_name)
35
- uri.query = build_query(default_arguments.merge(arguments))
55
+ # Call a named Esgob API function.
56
+ #
57
+ # @param [String] function_name The name of API function.
58
+ # @param [Hash] args Pairs of argument keys and values.
59
+ # @return [Hash] The response from the Esgob service, with symbols as keys.
60
+ # @example client.call('domains.slaves.add', :domain => 'example.com', :masterip => '192.168.0.1')
61
+ def call(function_name, args = {})
62
+ uri = URI(config.endpoint + function_name)
63
+ uri.query = build_query(default_arguments.merge(args))
36
64
 
37
65
  res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
38
66
  req = Net::HTTP::Get.new(uri.request_uri)
@@ -57,7 +85,8 @@ class Esgob::Client
57
85
  end
58
86
  end
59
87
 
60
- # Return account status; credit balance, etc
88
+ # Return account status; credit balance, etc.
89
+ # @return [Hash] Key, value pairs, containing account information.
61
90
  def accounts_get
62
91
  account = call('accounts.get')
63
92
  account[:added] = Time.at(account[:added]) if account[:added].is_a?(Fixnum)
@@ -65,12 +94,13 @@ class Esgob::Client
65
94
  end
66
95
 
67
96
  # Returns all hosted domains
97
+ # @return [Array<Hash>] Array of hashes, one per domain.
68
98
  def domains_list
69
99
  call('domains.list')[:domains]
70
100
  end
71
101
 
72
102
  # Returns all hosted slave domains as a hash
73
- #
103
+ # @return [Hash] Domain name as key, master ip as value
74
104
  def domains_slaves_list
75
105
  Hash[
76
106
  call('domains.slaves.list')[:domains].map do |item|
@@ -79,14 +109,19 @@ class Esgob::Client
79
109
  ]
80
110
  end
81
111
 
82
- # Adds a new slave domain
112
+ # Adds a new slave domain.
113
+ # @param [String] domain The name of the domain to add
114
+ # @param [String] masterip The IP of the master to transfer the zone from.
115
+ # @return [Hash] The response from the Esgob service, with symbols as keys.
83
116
  def domains_slaves_add(domain, masterip)
84
117
  result = call('domains.slaves.add', :domain => domain, :masterip => masterip)
85
118
  result[:domain] ||= domain
86
119
  result
87
120
  end
88
121
 
89
- # Deletes a slave domain
122
+ # Deletes a slave domain.
123
+ # @param [String] domain The name of the domain to delete.
124
+ # @return [Hash] The response from the Esgob service, with symbols as keys.
90
125
  def domains_slaves_delete(domain)
91
126
  result = call('domains.slaves.delete', :domain => domain)
92
127
  result[:domain] ||= domain
@@ -94,6 +129,8 @@ class Esgob::Client
94
129
  end
95
130
 
96
131
  # Force AXFR / transfer from master of a slave domain
132
+ # @param [String] domain The name of the domain to transfer.
133
+ # @return [Hash] The response from the Esgob service, with symbols as keys.
97
134
  def domains_slaves_forcetransfer(domain)
98
135
  result = call('domains.slaves.forcetransfer', :domain => domain)
99
136
  result[:domain] ||= domain
@@ -101,6 +138,9 @@ class Esgob::Client
101
138
  end
102
139
 
103
140
  # Updates the master IP of a slave domain
141
+ # @param [String] domain The name of the domain to update
142
+ # @param [String] masterip The new IP of the master to transfer the zone from.
143
+ # @return [Hash] The response from the Esgob service, with symbols as keys.
104
144
  def domains_slaves_updatemasterip(domain, masterip)
105
145
  result = call('domains.slaves.updatemasterip', :domain => domain, :masterip => masterip)
106
146
  result[:domain] ||= domain
@@ -108,6 +148,9 @@ class Esgob::Client
108
148
  end
109
149
 
110
150
  # Add a host allowed to AXFR out
151
+ # @param [String] domain The name of the domain to update
152
+ # @param [String] axfrip The new IP of the host to allow transfers to.
153
+ # @return [Hash] The response from the Esgob service, with symbols as keys.
111
154
  def domains_slaves_axfrout_add(domain, axfrip)
112
155
  result = call('domains.slaves.axfrout.add', :domain => domain, :axfrip => axfrip)
113
156
  result[:domain] ||= domain
@@ -115,6 +158,9 @@ class Esgob::Client
115
158
  end
116
159
 
117
160
  # Account Delete a host allowed to AXFR out
161
+ # @param [String] domain The name of the domain to update
162
+ # @param [String] axfrip The IP of the host to stop allowing transfers to.
163
+ # @return [Hash] The response from the Esgob service, with symbols as keys.
118
164
  def domains_slaves_axfrout_delete(domain, axfrip)
119
165
  result = call('domains.slaves.axfrout.delete', :domain => domain, :axfrip => axfrip)
120
166
  result[:domain] ||= domain
@@ -122,12 +168,17 @@ class Esgob::Client
122
168
  end
123
169
 
124
170
  # Retrieve the domain SOA serial number from the master and each anycast node
171
+ # @param [String] domain The name of the domain to look up
172
+ # @return [Hash] The response from the Esgob service, with symbols as keys.
125
173
  def domains_tools_soacheck(domain)
126
174
  call('domains.tools.soacheck', :domain => domain)
127
175
  end
128
176
 
129
177
  # Given a list of domains and a master IP, add and delete domains
130
178
  # so that the Esgob account matches the local list
179
+ # @param [Array<String>] domains The an array of domains to add to Esgob
180
+ # @param [String] masterip The master IP address to use for all the domains
181
+ # @return [Array<Hash>] A list of responses from the Esgob service
131
182
  def domains_slaves_sync(domains, masterip)
132
183
  existing_domains = domains_slaves_list
133
184
 
@@ -161,8 +212,9 @@ class Esgob::Client
161
212
  responses
162
213
  end
163
214
 
215
+ # @return [String]
164
216
  def inspect
165
- "\#<#{self.class} account=#{@account}>"
217
+ "\#<#{self.class} account=#{config.account}>"
166
218
  end
167
219
 
168
220
  protected
@@ -183,8 +235,8 @@ class Esgob::Client
183
235
 
184
236
  def default_arguments
185
237
  {
186
- :account => account,
187
- :key => api_key,
238
+ :account => config.account,
239
+ :key => config.key,
188
240
  :f => 'json'
189
241
  }
190
242
  end
@@ -0,0 +1,104 @@
1
+ class Esgob::Config
2
+ # Path to the configuration file
3
+ # @return [String]
4
+ attr_accessor :filepath
5
+ # @return [String]
6
+ attr_accessor :endpoint
7
+ # @return [String]
8
+ attr_accessor :account
9
+ # @return [String]
10
+ attr_accessor :key
11
+
12
+ DEFAULT_API_ENDPOINT = "https://api.esgob.com/1.0/".freeze
13
+
14
+ # @param [Hash] args
15
+ # @option args [String] :account The account name
16
+ # @option args [String] :key The API key
17
+ def initialize(args={})
18
+ args.each_pair { |k, v| send("#{k}=", v) }
19
+ end
20
+
21
+ def endpoint
22
+ # Use default endpoint if none configured
23
+ @endpoint || DEFAULT_API_ENDPOINT
24
+ end
25
+
26
+ # Get an ordered list of paths to possible Esgob configuration files
27
+ # @return [Array<String>] Array of file paths
28
+ def self.default_filepaths
29
+ [
30
+ File.join(ENV['HOME'], '.esgob'),
31
+ '/usr/local/etc/esgob.conf',
32
+ '/etc/esgob.conf'
33
+ ]
34
+ end
35
+
36
+ # Try and read Esgob configuration either from
37
+ # Environment variables or one of the config files
38
+ # @param [String] path Optional path to a configuration file
39
+ # @return Esgob::Config
40
+ def self.load(path=nil)
41
+ if !path.nil?
42
+ load_file(path)
43
+ elsif ENV['ESGOB_ACCOUNT'] and ENV['ESGOB_KEY']
44
+ self.new(
45
+ :account => ENV['ESGOB_ACCOUNT'],
46
+ :key => ENV['ESGOB_KEY']
47
+ )
48
+ else
49
+ default_filepaths.each do |path|
50
+ if File.exist?(path)
51
+ return load_file(path)
52
+ end
53
+ end
54
+
55
+ # No config file found, return nil
56
+ nil
57
+ end
58
+ end
59
+
60
+ # Save Esgob configuration to file
61
+ # If no filepath is given, save to the default filepath
62
+ # @param [String] path Optional path to a configuration file
63
+ def save(path=nil)
64
+ if !path.nil?
65
+ self.filepath = path
66
+ elsif filepath.nil?
67
+ self.filepath = self.class.default_filepaths.first
68
+ end
69
+
70
+ File.open(filepath, 'wb') do |file|
71
+ each_pair do |key,value|
72
+ file.puts "#{key} #{value}"
73
+ end
74
+ end
75
+ end
76
+
77
+ # Calls block once for each configuration key value pair,
78
+ # passing the key and value as parameters.
79
+ def each_pair
80
+ instance_variables.sort.each do |var|
81
+ next if var.to_s == '@filepath'
82
+ yield(var.to_s.sub(/^@/,''), instance_variable_get(var))
83
+ end
84
+ end
85
+
86
+
87
+ protected
88
+
89
+ def self.load_file(path)
90
+ config = self.new(:filepath => path)
91
+
92
+ File.foreach(path) do |line|
93
+ if line =~ /^(\w+)\s+(.+)$/
94
+ method, value = ["#{$1}=", $2]
95
+ if config.respond_to?(method)
96
+ config.send(method, value)
97
+ end
98
+ end
99
+ end
100
+
101
+ config
102
+ end
103
+
104
+ end
@@ -1,3 +1,3 @@
1
1
  module Esgob
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,6 +1,7 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
 
3
3
  require 'test_helper'
4
+ require 'thor'
4
5
  require 'esgob'
5
6
 
6
7
  class TestCLI < MiniTest::Unit::TestCase
@@ -8,16 +9,29 @@ class TestCLI < MiniTest::Unit::TestCase
8
9
  # Run before each test
9
10
  FakeWeb.clean_registry
10
11
 
11
- @client = Esgob::Client.new('acct', 'xxxx')
12
- Esgob::Client.stubs(:new).returns(@client)
13
-
14
12
  ENV['THOR_SHELL'] = 'Basic'
13
+ ENV['ESGOB_ACCOUNT'] = 'acct'
14
+ ENV['ESGOB_KEY'] = 'xxxx'
15
15
  end
16
16
 
17
17
  def teardown
18
18
  # Reset environment variables after each test
19
19
  ENV.delete('ESGOB_ACCOUNT')
20
- ENV.delete('ESGOB_API_KEY')
20
+ ENV.delete('ESGOB_KEY')
21
+ end
22
+
23
+ def test_config
24
+ shell = Thor::Base.shell.new
25
+ shell.expects(:ask).with("What is your Esgob account name?").returns('ask_acct')
26
+ shell.expects(:ask).with("What is your Esgob key?").returns('ask_key')
27
+
28
+ config = Esgob::Config.new
29
+ Esgob::Config.expects(:new).with().returns(config)
30
+ config.filepath = '/etc/esgob.conf'
31
+ config.expects(:save)
32
+
33
+ output = capture(:stdout) { Esgob::CLI.start(%w(config), :shell => shell) }
34
+ assert_equal "Configuration written to /etc/esgob.conf\n", output
21
35
  end
22
36
 
23
37
  def test_account
@@ -29,6 +43,14 @@ class TestCLI < MiniTest::Unit::TestCase
29
43
  assert_match " credits: 48\n", output
30
44
  end
31
45
 
46
+ def test_account_unconfigured
47
+ Esgob::Config.expects(:load).with().returns(nil)
48
+
49
+ output = capture(:stderr) { Esgob::CLI.start(%w(account)) }
50
+ assert_match "=> Error: Unable to load Esgob configuration\n", output
51
+ assert_match "Use the 'esgob config' command to create a configuration file.\n", output
52
+ end
53
+
32
54
  def test_account_error
33
55
  FakeWeb.register_uri(
34
56
  :get, %r{^https?://api\.esgob\.com(:443)?/},
@@ -102,9 +124,11 @@ class TestCLI < MiniTest::Unit::TestCase
102
124
  end
103
125
 
104
126
  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')
127
+ client = Esgob::Client.new
128
+ client.expects(:domains_slaves_list).with().returns('a.com' => '195.177.253.169', 'b.com' => '195.177.253.169')
129
+ client.expects(:domains_slaves_delete).with('a.com').returns(:action => 'domain deleted')
130
+ client.expects(:domains_slaves_add).with('c.com', '195.177.253.169').returns(:action => 'domain added')
131
+ Esgob::Client.stubs(:new).returns(client)
108
132
 
109
133
  output = capture(:stdout) { Esgob::CLI.start(['slaves-sync', fixture_path('sync-domain-list.txt'), '195.177.253.169']) }
110
134
  assert_match "a.com => domain deleted\n", output
@@ -5,7 +5,9 @@ require 'esgob'
5
5
 
6
6
  class TestClient < MiniTest::Unit::TestCase
7
7
  def setup
8
- # Run before each test
8
+ # Clear environment variables before each test
9
+ ENV.delete('ESGOB_ACCOUNT')
10
+ ENV.delete('ESGOB_KEY')
9
11
  FakeWeb.clean_registry
10
12
  @client = Esgob::Client.new('acct', 'xxxx')
11
13
  end
@@ -13,49 +15,74 @@ class TestClient < MiniTest::Unit::TestCase
13
15
  def teardown
14
16
  # Reset environment variables after each test
15
17
  ENV.delete('ESGOB_ACCOUNT')
16
- ENV.delete('ESGOB_API_KEY')
18
+ ENV.delete('ESGOB_KEY')
17
19
  end
18
20
 
19
21
  def test_new_client_using_environment
20
22
  ENV['ESGOB_ACCOUNT'] = 'envacct'
21
- ENV['ESGOB_API_KEY'] = 'envkey'
23
+ ENV['ESGOB_KEY'] = 'envkey'
22
24
 
23
25
  client = Esgob::Client.new
24
- assert_equal 'envacct', client.account
25
- assert_equal 'envkey', client.api_key
26
- assert_equal 'https://api.esgob.com/1.0/', client.endpoint
26
+ assert_equal 'envacct', client.config.account
27
+ assert_equal 'envkey', client.config.key
28
+ assert_equal 'https://api.esgob.com/1.0/', client.config.endpoint
27
29
  end
28
30
 
29
31
  def test_new_client_using_arguments
30
32
  client = Esgob::Client.new('foobar', 'mykey')
31
- assert_equal 'foobar', client.account
32
- assert_equal 'mykey', client.api_key
33
- assert_equal 'https://api.esgob.com/1.0/', client.endpoint
33
+ assert_equal 'foobar', client.config.account
34
+ assert_equal 'mykey', client.config.key
35
+ assert_equal 'https://api.esgob.com/1.0/', client.config.endpoint
34
36
  end
35
37
 
36
38
  def test_new_client_using_hash
37
39
  client = Esgob::Client.new(
38
40
  :account => 'hashacct',
39
- :api_key => 'hashkey',
41
+ :key => 'hashkey',
40
42
  :endpoint => 'http://api.example.com/'
41
43
  )
42
- assert_equal 'hashacct', client.account
43
- assert_equal 'hashkey', client.api_key
44
- assert_equal 'http://api.example.com/', client.endpoint
44
+ assert_equal 'hashacct', client.config.account
45
+ assert_equal 'hashkey', client.config.key
46
+ assert_equal 'http://api.example.com/', client.config.endpoint
47
+ end
48
+
49
+ def test_new_client_using_config
50
+ config = Esgob::Config.new(
51
+ :account => 'confacct',
52
+ :key => 'confkey'
53
+ )
54
+ client = Esgob::Client.new(config)
55
+ assert_equal 'confacct', client.config.account
56
+ assert_equal 'confkey', client.config.key
57
+ end
58
+
59
+ def test_new_client_with_no_config_files
60
+ Esgob::Config.expects(:default_filepaths).with().returns([])
61
+ err = assert_raises(Esgob::UnconfiguredError) { Esgob::Client.new }
62
+ assert_equal 'Unable to load Esgob configuration', err.message
45
63
  end
46
64
 
47
65
  def test_new_client_with_no_account
48
66
  ENV.delete('ESGOB_ACCOUNT')
49
- assert_raises(ArgumentError) do
67
+ err = assert_raises(ArgumentError) do
50
68
  Esgob::Client.new(nil, 'mykey')
51
69
  end
70
+ assert_equal 'No account name configured for Esgob', err.message
52
71
  end
53
72
 
54
- def test_new_client_with_no_api_key
55
- ENV.delete('ESGOB_API_KEY')
56
- assert_raises(ArgumentError) do
73
+ def test_new_client_with_no_key
74
+ ENV.delete('ESGOB_KEY')
75
+ err = assert_raises(ArgumentError) do
57
76
  Esgob::Client.new('acct', nil)
58
77
  end
78
+ assert_equal 'No API key configured for Esgob', err.message
79
+ end
80
+
81
+ def test_new_client_unsupported_arguments
82
+ err = assert_raises(ArgumentError) do
83
+ Esgob::Client.new(1, 2, 3, 4)
84
+ end
85
+ assert_equal 'Unsupported arguments for creating Esgob::Client', err.message
59
86
  end
60
87
 
61
88
  def test_call_with_no_parameters
@@ -145,7 +172,7 @@ class TestClient < MiniTest::Unit::TestCase
145
172
  {
146
173
  :credits => 48,
147
174
  :users => [],
148
- :added => Time.parse('2015-02-01 12:07:14 +0000'),
175
+ :added => Time.utc(2015, 2, 1, 12, 07, 14),
149
176
  :id => 'xyz',
150
177
  :name => 'Person Name'
151
178
  },
@@ -0,0 +1,151 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ require 'test_helper'
4
+ require 'tempfile'
5
+ require 'esgob'
6
+
7
+ class TestConfig < MiniTest::Unit::TestCase
8
+ def setup
9
+ # Clear environment variables before each test
10
+ ENV.delete('ESGOB_ACCOUNT')
11
+ ENV.delete('ESGOB_KEY')
12
+ end
13
+
14
+ def teardown
15
+ # Reset environment variables after each test
16
+ ENV.delete('ESGOB_ACCOUNT')
17
+ ENV.delete('ESGOB_KEY')
18
+ end
19
+
20
+ def test_new
21
+ conf = Esgob::Config.new(:account => 'acct', :key => 'xyz')
22
+ assert_instance_of(Esgob::Config, conf)
23
+ assert_equal('acct', conf.account)
24
+ assert_equal('xyz', conf.key)
25
+ end
26
+
27
+ def test_default_values
28
+ conf = Esgob::Config.new
29
+ assert_instance_of(Esgob::Config, conf)
30
+ assert_equal(nil, conf.account)
31
+ assert_equal('https://api.esgob.com/1.0/', conf.endpoint)
32
+ assert_equal(nil, conf.key)
33
+ end
34
+
35
+ def test_default_filepaths
36
+ ENV['HOME'] = '/home/bob'
37
+ assert_instance_of(Array, Esgob::Config.default_filepaths)
38
+ assert_includes(Esgob::Config.default_filepaths, '/home/bob/.esgob')
39
+ assert_includes(Esgob::Config.default_filepaths, '/etc/esgob.conf')
40
+ end
41
+
42
+ def test_load_from_env
43
+ ENV['ESGOB_ACCOUNT'] = 'envacct'
44
+ ENV['ESGOB_KEY'] = 'envkey'
45
+ conf = Esgob::Config.load
46
+ assert_instance_of(Esgob::Config, conf)
47
+ assert_equal('envacct', conf.account)
48
+ assert_equal('envkey', conf.key)
49
+ assert_equal(nil, conf.filepath)
50
+ end
51
+
52
+ def test_load_from_specific_file
53
+ conf = Esgob::Config.load(fixture_path('config.txt'))
54
+ assert_instance_of(Esgob::Config, conf)
55
+ assert_equal('fileacct', conf.account)
56
+ assert_equal('filekey', conf.key)
57
+ assert_match(/test\/fixtures\/config\.txt$/, conf.filepath)
58
+ end
59
+
60
+ def test_load_from_default_files
61
+ Esgob::Config.expects(:default_filepaths).with().returns([
62
+ '/doesnt/exist/shuuKee6',
63
+ '/doesnt/exist/ebah4kiH',
64
+ fixture_path('config.txt'),
65
+ '/doesnt/exist/Va5cu9en',
66
+ ])
67
+
68
+ conf = Esgob::Config.load
69
+ assert_instance_of(Esgob::Config, conf)
70
+ assert_equal('fileacct', conf.account)
71
+ assert_equal('filekey', conf.key)
72
+ assert_match(/test\/fixtures\/config\.txt$/, conf.filepath)
73
+ end
74
+
75
+ def test_load_unavailable
76
+ Esgob::Config.expects(:default_filepaths).with().returns([
77
+ '/doesnt/exist/shuuKee6'
78
+ ])
79
+
80
+ conf = Esgob::Config.load
81
+ assert_nil(conf)
82
+ end
83
+
84
+ def test_each_pair
85
+ conf = Esgob::Config.new(:key => 'xyz', :account => 'abc')
86
+ array = []
87
+ conf.each_pair { |k, v| array << "#{k}=#{v}" }
88
+ assert_equal(["account=abc", "key=xyz"], array)
89
+ end
90
+
91
+ def test_save_config_to_default
92
+ tempfile = Tempfile.new('esgob-config-test')
93
+ tempfile.close
94
+
95
+ Esgob::Config.expects(:default_filepaths).with().returns([tempfile.path])
96
+
97
+ config = Esgob::Config.new
98
+ config.account = 'a'
99
+ config.key = 'k'
100
+ config.save
101
+
102
+ assert_equal(
103
+ "account a\n"+
104
+ "key k\n",
105
+ tempfile.open.read
106
+ )
107
+
108
+ assert_equal(tempfile.path, config.filepath)
109
+
110
+ tempfile.unlink
111
+ end
112
+
113
+ def test_save_config_with_path
114
+ tempfile = Tempfile.new('esgob-config-test')
115
+ tempfile.close
116
+
117
+ config = Esgob::Config.new
118
+ config.account = 'a'
119
+ config.key = 'k'
120
+ config.save(tempfile.path)
121
+
122
+ assert_equal(
123
+ "account a\n"+
124
+ "key k\n",
125
+ tempfile.open.read
126
+ )
127
+
128
+ tempfile.unlink
129
+ end
130
+
131
+ def test_save_config_with_custom_endpoint
132
+ tempfile = Tempfile.new('esgob-config-test')
133
+ tempfile.close
134
+
135
+ config = Esgob::Config.new
136
+ config.account = 'a'
137
+ config.key = 'k'
138
+ config.endpoint = 'http://esgob.example.com/'
139
+ config.save(tempfile.path)
140
+
141
+ assert_equal(
142
+ "account a\n"+
143
+ "endpoint http://esgob.example.com/\n"+
144
+ "key k\n",
145
+ tempfile.open.read
146
+ )
147
+
148
+ tempfile.unlink
149
+ end
150
+
151
+ end
@@ -0,0 +1,5 @@
1
+ # Comments allowed
2
+ account fileacct
3
+
4
+ key filekey
5
+
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.2
4
+ version: 0.0.3
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-05-03 00:00:00.000000000 Z
11
+ date: 2015-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -141,13 +141,16 @@ files:
141
141
  - lib/esgob.rb
142
142
  - lib/esgob/cli.rb
143
143
  - lib/esgob/client.rb
144
+ - lib/esgob/config.rb
144
145
  - lib/esgob/version.rb
145
146
  - test/esgob_cli_test.rb
146
147
  - test/esgob_client_test.rb
148
+ - test/esgob_config_test.rb
147
149
  - test/esgob_version_test.rb
148
150
  - test/fixtures/accounts_get.json
149
151
  - test/fixtures/code_1003.json
150
152
  - test/fixtures/code_2007.json
153
+ - test/fixtures/config.txt
151
154
  - test/fixtures/domains_list.json
152
155
  - test/fixtures/domains_slaves_add.json
153
156
  - test/fixtures/domains_slaves_axfrout_add.json
@@ -186,10 +189,12 @@ summary: Client library for talking to the Esgob anycast DNS API.
186
189
  test_files:
187
190
  - test/esgob_cli_test.rb
188
191
  - test/esgob_client_test.rb
192
+ - test/esgob_config_test.rb
189
193
  - test/esgob_version_test.rb
190
194
  - test/fixtures/accounts_get.json
191
195
  - test/fixtures/code_1003.json
192
196
  - test/fixtures/code_2007.json
197
+ - test/fixtures/config.txt
193
198
  - test/fixtures/domains_list.json
194
199
  - test/fixtures/domains_slaves_add.json
195
200
  - test/fixtures/domains_slaves_axfrout_add.json