3scale-3scale_ws_api_for_ruby 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README +63 -0
- data/Rakefile +29 -0
- data/init.rb +1 -0
- data/lib/3scale/interface.rb +236 -0
- data/lib/3scale_interface.rb +1 -0
- data/test/interface_test.rb +218 -0
- metadata +67 -0
data/README
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
= Interface for 3scale web service API monitoring system
|
2
|
+
|
3
|
+
This plugin provides interface for communication with 3scale monitoring system.
|
4
|
+
|
5
|
+
== Configuration
|
6
|
+
|
7
|
+
If you are using rails 2.1 or newer, put this into your config/environment.rb
|
8
|
+
file:
|
9
|
+
|
10
|
+
config.gem "3scale_interface"
|
11
|
+
|
12
|
+
If you are using older version, put there this instead:
|
13
|
+
|
14
|
+
require "3scale_interface"
|
15
|
+
|
16
|
+
== Usage
|
17
|
+
|
18
|
+
First, create new interface object with 3scale backed hostname and Your
|
19
|
+
private authentication key:
|
20
|
+
|
21
|
+
interface = ThreeScale::Interface.new("http://3scale.net", "a3b034...")
|
22
|
+
|
23
|
+
Because the object is stateless, you can create just one and store it globally.
|
24
|
+
|
25
|
+
Then for each request to Your service:
|
26
|
+
|
27
|
+
1. Start the transaction with user key and (optionally) estimated resource
|
28
|
+
usage (in this example it is: 1 hit and 42000 kilobytes of storage space),
|
29
|
+
|
30
|
+
transaction = interface.start(user_key, 'hits' => 1, 'storage' => 42000)
|
31
|
+
|
32
|
+
This will return transaction data (if successful). It is a hash containing
|
33
|
+
these fields:
|
34
|
+
|
35
|
+
<tt>:id</tt>::
|
36
|
+
transaction id necessary for confirmation or cancellation of transaction
|
37
|
+
(see following steps).
|
38
|
+
|
39
|
+
<tt>:provider_verification_key</tt>::
|
40
|
+
the provider should send this key back to user so he/she can verify the
|
41
|
+
authenticity of the response.
|
42
|
+
|
43
|
+
<tt>:contract_name</tt>::
|
44
|
+
name of contract the user is signed for. This can be used to send
|
45
|
+
different response according to contract type, if that is desired.
|
46
|
+
|
47
|
+
2. Process the request.
|
48
|
+
|
49
|
+
2a. If the processing was successful:
|
50
|
+
Call +confirm+:
|
51
|
+
|
52
|
+
interface.confirm(transaction[:id])
|
53
|
+
|
54
|
+
Or call it with actual resource usage, if it differs from predicted one:
|
55
|
+
|
56
|
+
interface.confirm(transaction[:id], 'hits' => 1, 'storage' => 40500)
|
57
|
+
|
58
|
+
2b. If there was some error, call +cancel+:
|
59
|
+
|
60
|
+
interface.cancel(transaction[:id])
|
61
|
+
|
62
|
+
3. Send response back to the user together with +provider_verification_key+.
|
63
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
desc 'Default: run unit tests.'
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
desc 'Run unit tests.'
|
10
|
+
Rake::TestTask.new(:test) do |t|
|
11
|
+
t.libs << 'lib'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = '3scale interface'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
24
|
+
|
25
|
+
spec = eval(File.read(File.dirname(__FILE__) + '/3scale_ws_api_for_ruby.gemspec'))
|
26
|
+
|
27
|
+
Rake::GemPackageTask.new(spec) do |package|
|
28
|
+
package.need_tar = true
|
29
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/lib/3scale_interface"
|
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'hpricot'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module ThreeScale # :nodoc:
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
8
|
+
# Base class for exceptions caused by user.
|
9
|
+
class UserError < Error; end
|
10
|
+
|
11
|
+
# Exception raised when contract between user and provider is not active.
|
12
|
+
# Contract can be inactive when it is pending (requires confirmation from
|
13
|
+
# provider), suspended or canceled.
|
14
|
+
class ContractNotActive < UserError; end
|
15
|
+
|
16
|
+
# Exception raised when usage limits configured for contract are already
|
17
|
+
# exceeded.
|
18
|
+
class LimitsExceeded < UserError; end
|
19
|
+
|
20
|
+
# Exception raised when +user_key+ is not valid. This can mean that contract
|
21
|
+
# between provider and user does not exists, or the passed +user_key+ does
|
22
|
+
# not correspond to the key associated with this contract.
|
23
|
+
class UserKeyInvalid < UserError; end
|
24
|
+
|
25
|
+
|
26
|
+
# Base class for exceptions caused by provider.
|
27
|
+
class ProviderError < Error; end
|
28
|
+
|
29
|
+
# Exception raised when some metric name in provider +usage+ hash does not
|
30
|
+
# correspond to metric configured for the service.
|
31
|
+
class MetricInvalid < ProviderError; end
|
32
|
+
|
33
|
+
# Exception raised when provider authentication key is not valid. The provider
|
34
|
+
# needs to make sure that the key used is the same as the one that was
|
35
|
+
# generated for him/her when he/she published a service on 3scale.
|
36
|
+
class ProviderKeyInvalid < ProviderError; end
|
37
|
+
|
38
|
+
# Exception raised when transaction corresponding to given +transaction_id+
|
39
|
+
# does not exists. Methods +confirm+ and +cancel+ need valid transaction id
|
40
|
+
# that is obtained by preceding call to +start+.
|
41
|
+
class TransactionNotFound < ProviderError; end
|
42
|
+
|
43
|
+
|
44
|
+
# Base class for exceptions caused by 3scale backend system.
|
45
|
+
class SystemError < Error; end
|
46
|
+
|
47
|
+
# Other error.
|
48
|
+
class UnknownError < SystemError; end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
# This class provides interface to 3scale monitoring system.
|
53
|
+
#
|
54
|
+
# Objects of this class are stateless and can be shared through multiple
|
55
|
+
# transactions and by multiple clients.
|
56
|
+
class Interface
|
57
|
+
|
58
|
+
# Hostname of 3scale server.
|
59
|
+
attr_accessor :host
|
60
|
+
|
61
|
+
# Key that uniquely identifies the provider. This key is known only to the
|
62
|
+
# provider and to 3scale.
|
63
|
+
attr_accessor :provider_authentication_key
|
64
|
+
|
65
|
+
# Create a 3scale interface object.
|
66
|
+
#
|
67
|
+
# == Arguments
|
68
|
+
# +host+:: Hostname of 3scale backend server.
|
69
|
+
# +provider_authentication_key+:: Unique key that identifies this provider.
|
70
|
+
def initialize(host = nil, provider_authentication_key = nil)
|
71
|
+
@host = host
|
72
|
+
@provider_authentication_key = provider_authentication_key
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# Starts a transaction. This can be used also to report estimated resource
|
77
|
+
# usage of the request.
|
78
|
+
#
|
79
|
+
# == Arguments
|
80
|
+
# +user_key+:: Key that uniquely identifies an user of the service.
|
81
|
+
# +usage+::
|
82
|
+
# A hash of metric names/values pairs that contains predicted resource
|
83
|
+
# usage of this request.
|
84
|
+
#
|
85
|
+
# For example, if this request is going to take 10MB of storage space,
|
86
|
+
# then this parameter could contain {'storage' => 10}. The values may be
|
87
|
+
# only approximate or they can be missing altogether. In these cases, the
|
88
|
+
# real values must be reported using method +confirm+.
|
89
|
+
#
|
90
|
+
# == Return values
|
91
|
+
# A hash containing there keys:
|
92
|
+
# <tt>:id</tt>::
|
93
|
+
# Transaction id. This is required for confirmation/cancellation of the
|
94
|
+
# transaction later.
|
95
|
+
# <tt>:provider_verification_key</tt>::
|
96
|
+
# This key should be sent back to the user so he/she can use it to verify
|
97
|
+
# the authenticity of the provider.
|
98
|
+
# <tt>:contract_name</tt>::
|
99
|
+
# This is name of the contract the user is singed for. This information
|
100
|
+
# can be used to serve different responses according to contract types,
|
101
|
+
# if that is desirable.
|
102
|
+
#
|
103
|
+
# == Exceptions
|
104
|
+
#
|
105
|
+
# ThreeScale::UserKeyInvalid:: +user_key+ is not valid
|
106
|
+
# ThreeScale::ProviderKeyInvalid:: +provider_authentication_key+ is not valid
|
107
|
+
# ThreeScale::MetricInvalid:: +usage+ contains invalid metrics
|
108
|
+
# ThreeScale::ContractNotActive:: contract is not active
|
109
|
+
# ThreeScale::LimitsExceeded:: usage limits are exceeded
|
110
|
+
# ThreeScale::UnknownError:: some other unexpected error
|
111
|
+
#
|
112
|
+
def start(user_key, usage = {})
|
113
|
+
uri = URI.parse("#{host}/transactions.xml")
|
114
|
+
params = {
|
115
|
+
'user_key' => prepare_key(user_key),
|
116
|
+
'provider_key' => provider_authentication_key
|
117
|
+
}
|
118
|
+
params.merge!(encode_params(usage, 'usage'))
|
119
|
+
response = Net::HTTP.post_form(uri, params)
|
120
|
+
|
121
|
+
if response.is_a?(Net::HTTPSuccess)
|
122
|
+
element = Hpricot::XML(response.body).at('transaction')
|
123
|
+
[:id, :provider_verification_key, :contract_name].inject({}) do |memo, key|
|
124
|
+
memo[key] = element.at(key).inner_text if element.at(key)
|
125
|
+
memo
|
126
|
+
end
|
127
|
+
else
|
128
|
+
handle_error(response.body)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Confirms a transaction.
|
133
|
+
#
|
134
|
+
# == Arguments
|
135
|
+
#
|
136
|
+
# +transaction_id+::
|
137
|
+
# A transaction id obtained from previous call to +start+.
|
138
|
+
# +usage+::
|
139
|
+
# A hash of metric names/values pairs containing actual resource usage
|
140
|
+
# of this request. This parameter is required only if no usage information
|
141
|
+
# was passed to method +start+ for this transaction, or if it was only
|
142
|
+
# approximate.
|
143
|
+
#
|
144
|
+
# == Return values
|
145
|
+
#
|
146
|
+
# If there were no exceptions raised, returns true.
|
147
|
+
#
|
148
|
+
# == Exceptions
|
149
|
+
#
|
150
|
+
# ThreeScale::TransactionNotFound:: transactions does not exits
|
151
|
+
# ThreeScale::ProviderKeyInvalid:: +provider_authentication_key+ is not valid
|
152
|
+
# ThreeScale::MetricInvalid:: +usage+ contains invalid metrics
|
153
|
+
# ThreeScale::UnknownError:: some other unexpected error
|
154
|
+
#
|
155
|
+
def confirm(transaction_id, usage = {})
|
156
|
+
uri = URI.parse("#{host}/transactions/#{CGI.escape(transaction_id.to_s)}/confirm.xml")
|
157
|
+
params = {
|
158
|
+
'provider_key' => provider_authentication_key
|
159
|
+
}
|
160
|
+
params.merge!(encode_params(usage, 'usage'))
|
161
|
+
|
162
|
+
response = Net::HTTP.post_form(uri, params)
|
163
|
+
response.is_a?(Net::HTTPSuccess) ? true : handle_error(response.body)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Cancels a transaction.
|
167
|
+
#
|
168
|
+
# Use this if request processing failed. Any estimated resource usage
|
169
|
+
# reported by preceding call to +start+ will be deleted. You don't have to
|
170
|
+
# call this if call to +start+ itself failed.
|
171
|
+
#
|
172
|
+
# == Arguments
|
173
|
+
#
|
174
|
+
# +transaction_id+::
|
175
|
+
# A transaction id obtained from previous call to +start+.
|
176
|
+
#
|
177
|
+
# == Return values
|
178
|
+
#
|
179
|
+
# If there were no exceptions raised, returns true.
|
180
|
+
#
|
181
|
+
# == Exceptions
|
182
|
+
#
|
183
|
+
# ThreeScale::TransactionNotFound:: transactions does not exits
|
184
|
+
# ThreeScale::ProviderKeyInvalid:: +provider_authentication_key+ is not valid
|
185
|
+
# ThreeScale::UnknownError:: some other unexpected error
|
186
|
+
#
|
187
|
+
def cancel(transaction_id)
|
188
|
+
uri = URI.parse("#{host}/transactions/#{CGI.escape(transaction_id.to_s)}.xml" +
|
189
|
+
"?provider_key=#{CGI.escape(provider_authentication_key)}")
|
190
|
+
|
191
|
+
response = Net::HTTP.start(uri.host, uri.port) do |http|
|
192
|
+
http.delete("#{uri.path}?#{uri.query}")
|
193
|
+
end
|
194
|
+
|
195
|
+
response.is_a?(Net::HTTPSuccess) ? true : handle_error(response.body)
|
196
|
+
end
|
197
|
+
|
198
|
+
KEY_PREFIX = '3scale-' # :nodoc:
|
199
|
+
|
200
|
+
# This can be used to quickly distinguish between keys used with 3scale
|
201
|
+
# system and any other keys the provider might use. Returns true if the key
|
202
|
+
# is for 3scale system.
|
203
|
+
def system_key?(key)
|
204
|
+
# Key should start with prefix
|
205
|
+
key.index(KEY_PREFIX) == 0
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
# Encode hash into form suitable for sending it as params of HTTP request.
|
211
|
+
def encode_params(params, prefix)
|
212
|
+
params.inject({}) do |memo, (key, value)|
|
213
|
+
memo["#{prefix}[#{CGI.escape(key)}]"] = CGI.escape(value.to_s)
|
214
|
+
memo
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def prepare_key(key)
|
219
|
+
system_key?(key) ? key[KEY_PREFIX.length..-1] : key
|
220
|
+
end
|
221
|
+
|
222
|
+
CODES_TO_EXCEPTIONS = {
|
223
|
+
'user.exceeded_limits' => LimitsExceeded,
|
224
|
+
'user.invalid_key' => UserKeyInvalid,
|
225
|
+
'user.inactive_contract' => ContractNotActive,
|
226
|
+
'provider.invalid_key' => ProviderKeyInvalid,
|
227
|
+
'provider.invalid_metric' => MetricInvalid,
|
228
|
+
'provider.invalid_transaction_id' => TransactionNotFound} # :nodoc:
|
229
|
+
|
230
|
+
def handle_error(response)
|
231
|
+
element = Hpricot::XML(response).at('error')
|
232
|
+
raise UnknownError unless element
|
233
|
+
raise CODES_TO_EXCEPTIONS[element[:id]] || UnknownError, element.inner_text
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/3scale/interface"
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'activesupport'
|
3
|
+
require 'fake_web'
|
4
|
+
require 'mocha'
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
require "#{File.dirname(__FILE__)}/../lib/3scale/interface"
|
8
|
+
|
9
|
+
class InterfaceTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
@interface = ThreeScale::Interface.new('http://3scale.net', 'some_key')
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_start_should_raise_exception_on_invalid_user_key
|
15
|
+
FakeWeb.register_uri('http://3scale.net/transactions.xml',
|
16
|
+
:status => ['403', 'Forbidden'],
|
17
|
+
:string => stub_error('user.invalid_key'))
|
18
|
+
|
19
|
+
assert_raise ThreeScale::UserKeyInvalid do
|
20
|
+
@interface.start('invalid_key')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_start_should_raise_exception_on_invalid_provider_key
|
25
|
+
FakeWeb.register_uri('http://3scale.net/transactions.xml',
|
26
|
+
:status => ['403', 'Forbidden'],
|
27
|
+
:string => stub_error('provider.invalid_key'))
|
28
|
+
|
29
|
+
assert_raise ThreeScale::ProviderKeyInvalid do
|
30
|
+
@interface.start('valid_key')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_start_should_raise_exception_on_inactive_contract
|
35
|
+
FakeWeb.register_uri('http://3scale.net/transactions.xml',
|
36
|
+
:status => ['403', 'Forbidden'],
|
37
|
+
:string => stub_error('user.inactive_contract'))
|
38
|
+
|
39
|
+
assert_raise ThreeScale::ContractNotActive do
|
40
|
+
@interface.start('valid_key', 'clicks' => 1)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_start_should_raise_exception_on_invalid_metric
|
45
|
+
FakeWeb.register_uri('http://3scale.net/transactions.xml',
|
46
|
+
:status => ['400', 'Bad Request'],
|
47
|
+
:string => stub_error('provider.invalid_metric'))
|
48
|
+
|
49
|
+
assert_raise ThreeScale::MetricInvalid do
|
50
|
+
@interface.start('valid_key', 'clicks' => 1)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_start_should_raise_exception_on_exceeded_limits
|
55
|
+
FakeWeb.register_uri('http://3scale.net/transactions.xml',
|
56
|
+
:status => ['403', 'Forbidden'],
|
57
|
+
:string => stub_error('user.exceeded_limits'))
|
58
|
+
|
59
|
+
assert_raise ThreeScale::LimitsExceeded do
|
60
|
+
@interface.start('valid_key', 'clicks' => 1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_start_should_raise_exception_on_unexpected_error
|
65
|
+
FakeWeb.register_uri('http://3scale.net/transactions.xml',
|
66
|
+
:status => ['500', 'Internal Server Error'])
|
67
|
+
|
68
|
+
assert_raise ThreeScale::UnknownError do
|
69
|
+
@interface.start('valid_key', 'clicks' => 1)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_start_should_send_usage_data
|
74
|
+
Net::HTTP.expects(:post_form).
|
75
|
+
with(anything, has_entries('usage[hits]' => '1')).
|
76
|
+
returns(stub_response)
|
77
|
+
|
78
|
+
@interface.start('valid_key', 'hits' => 1)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_start_should_return_transaction_data_on_success
|
82
|
+
FakeWeb.register_uri('http://3scale.net/transactions.xml',
|
83
|
+
:status => ['200', 'OK'],
|
84
|
+
:string => {:id => '42', :provider_verification_key => 'some_key',
|
85
|
+
:contract_name => 'ultimate'}.to_xml(:root => 'transaction',
|
86
|
+
:dasherize => false))
|
87
|
+
|
88
|
+
result = @interface.start('valid_key', {'clicks' => 1})
|
89
|
+
|
90
|
+
assert_equal '42', result[:id]
|
91
|
+
assert_equal 'some_key', result[:provider_verification_key]
|
92
|
+
assert_equal 'ultimate', result[:contract_name]
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_start_should_strip_3scale_prefix_from_user_key_before_sending
|
96
|
+
Net::HTTP.expects(:post_form).with(anything,
|
97
|
+
has_entries('user_key' => 'foo')).returns(stub_response)
|
98
|
+
|
99
|
+
@interface.start('3scale-foo')
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_start_should_leave_user_key_unchanged_if_it_does_not_contain_3scale_prefix
|
103
|
+
Net::HTTP.expects(:post_form).with(anything,
|
104
|
+
has_entries('user_key' => 'foo')).returns(stub_response)
|
105
|
+
|
106
|
+
@interface.start('foo')
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_confirm_should_raise_exception_on_invalid_transaction
|
110
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42/confirm.xml',
|
111
|
+
:status => ['404', 'Not Found'],
|
112
|
+
:string => stub_error('provider.invalid_transaction_id'))
|
113
|
+
|
114
|
+
assert_raise ThreeScale::TransactionNotFound do
|
115
|
+
@interface.confirm(42)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_confirm_should_raise_exception_on_invalid_provider_key
|
120
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42/confirm.xml',
|
121
|
+
:status => ['403', 'Forbidden'],
|
122
|
+
:string => stub_error('provider.invalid_key'))
|
123
|
+
|
124
|
+
assert_raise ThreeScale::ProviderKeyInvalid do
|
125
|
+
@interface.confirm(42)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_confirm_should_raise_exception_on_invalid_metric
|
130
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42/confirm.xml',
|
131
|
+
:status => ['400', 'Bad Request'],
|
132
|
+
:string => stub_error('provider.invalid_metric'))
|
133
|
+
|
134
|
+
assert_raise ThreeScale::MetricInvalid do
|
135
|
+
@interface.confirm(42, 'clicks' => 1)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_confirm_should_raise_exception_on_unexpected_error
|
140
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42/confirm.xml',
|
141
|
+
:status => ['500', 'Internal Server Error'])
|
142
|
+
|
143
|
+
assert_raise ThreeScale::UnknownError do
|
144
|
+
@interface.confirm(42)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_confirm_should_return_true_on_success
|
149
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42/confirm.xml',
|
150
|
+
:status => ['200', 'OK'])
|
151
|
+
|
152
|
+
result = @interface.confirm(42, 'clicks' => 1)
|
153
|
+
assert_equal true, result
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_confirm_should_send_usage_data
|
157
|
+
Net::HTTP.expects(:post_form).
|
158
|
+
with(anything, has_entries('usage[hits]' => '1')).
|
159
|
+
returns(stub_response)
|
160
|
+
|
161
|
+
@interface.confirm(42, 'hits' => 1)
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_cancel_should_raise_exception_on_invalid_transaction
|
165
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42.xml?provider_key=some_key',
|
166
|
+
:status => ['404', 'Not Found'],
|
167
|
+
:string => stub_error('provider.invalid_transaction_id'))
|
168
|
+
|
169
|
+
assert_raise ThreeScale::TransactionNotFound do
|
170
|
+
@interface.cancel(42)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_cancel_should_raise_exception_on_invalid_provider_key
|
175
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42.xml?provider_key=some_key',
|
176
|
+
:status => ['403', 'Forbidden'],
|
177
|
+
:string => stub_error('provider.invalid_key'))
|
178
|
+
|
179
|
+
assert_raise ThreeScale::ProviderKeyInvalid do
|
180
|
+
@interface.cancel(42)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_cancel_should_raise_exception_on_unexpected_error
|
185
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42.xml?provider_key=some_key',
|
186
|
+
:status => ['500', 'Internal Server Error'])
|
187
|
+
|
188
|
+
assert_raise ThreeScale::UnknownError do
|
189
|
+
@interface.cancel(42)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_cancel_should_return_true_on_success
|
194
|
+
FakeWeb.register_uri('http://3scale.net/transactions/42.xml?provider_key=some_key',
|
195
|
+
:status => ['200', 'OK'])
|
196
|
+
|
197
|
+
result = @interface.cancel(42)
|
198
|
+
assert_equal true, result
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_should_identify_3scale_keys
|
202
|
+
assert @interface.system_key?('3scale-foo')
|
203
|
+
assert !@interface.system_key?('foo')
|
204
|
+
end
|
205
|
+
|
206
|
+
private
|
207
|
+
|
208
|
+
def stub_error(id)
|
209
|
+
"<error id=\"#{id}\">blah blah</error>"
|
210
|
+
end
|
211
|
+
|
212
|
+
def stub_response
|
213
|
+
response = stub
|
214
|
+
response.stubs(:is_a?).with(Net::HTTPSuccess).returns(true)
|
215
|
+
response.stubs(:body).returns('<transaction></transaction>')
|
216
|
+
response
|
217
|
+
end
|
218
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: 3scale-3scale_ws_api_for_ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Adam Cig\xC3\xA1nek"
|
8
|
+
- Josep M. Pujol
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2008-10-27 00:00:00 -07:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: hpricot
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.6.161
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: adam@3scale.net
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
files:
|
34
|
+
- init.rb
|
35
|
+
- lib/3scale/interface.rb
|
36
|
+
- lib/3scale_interface.rb
|
37
|
+
- README
|
38
|
+
- Rakefile
|
39
|
+
- test/interface_test.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://www.3scale.net
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.2.0
|
63
|
+
signing_key:
|
64
|
+
specification_version: 2
|
65
|
+
summary: 3scale web service management API for Ruby.
|
66
|
+
test_files:
|
67
|
+
- test/interface_test.rb
|