pisoni 1.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/Gemfile +16 -0
  4. data/LICENSE +202 -0
  5. data/Makefile +73 -0
  6. data/NOTICE +15 -0
  7. data/README.md +47 -0
  8. data/Rakefile +27 -0
  9. data/lib/3scale/core/alert_limit.rb +32 -0
  10. data/lib/3scale/core/api_client/attributes.rb +56 -0
  11. data/lib/3scale/core/api_client/collection.rb +19 -0
  12. data/lib/3scale/core/api_client/operations.rb +233 -0
  13. data/lib/3scale/core/api_client/resource.rb +52 -0
  14. data/lib/3scale/core/api_client/support.rb +55 -0
  15. data/lib/3scale/core/api_client.rb +5 -0
  16. data/lib/3scale/core/application.rb +67 -0
  17. data/lib/3scale/core/application_key.rb +34 -0
  18. data/lib/3scale/core/application_referrer_filter.rb +33 -0
  19. data/lib/3scale/core/errors.rb +130 -0
  20. data/lib/3scale/core/event.rb +26 -0
  21. data/lib/3scale/core/logger.rb +12 -0
  22. data/lib/3scale/core/metric.rb +32 -0
  23. data/lib/3scale/core/service.rb +82 -0
  24. data/lib/3scale/core/service_error.rb +34 -0
  25. data/lib/3scale/core/service_token.rb +39 -0
  26. data/lib/3scale/core/transaction.rb +26 -0
  27. data/lib/3scale/core/usage_limit.rb +40 -0
  28. data/lib/3scale/core/user.rb +47 -0
  29. data/lib/3scale/core/utilization.rb +28 -0
  30. data/lib/3scale/core/version.rb +5 -0
  31. data/lib/3scale/core.rb +63 -0
  32. data/lib/3scale_core.rb +1 -0
  33. data/lib/pisoni.rb +5 -0
  34. data/pisoni.gemspec +43 -0
  35. data/spec/alert_limit_spec.rb +72 -0
  36. data/spec/application_key_spec.rb +97 -0
  37. data/spec/application_referrer_filter_spec.rb +57 -0
  38. data/spec/application_spec.rb +188 -0
  39. data/spec/event_spec.rb +82 -0
  40. data/spec/metric_spec.rb +115 -0
  41. data/spec/private_endpoints/event.rb +9 -0
  42. data/spec/private_endpoints/service_error.rb +10 -0
  43. data/spec/private_endpoints/transaction.rb +16 -0
  44. data/spec/service_error_spec.rb +128 -0
  45. data/spec/service_spec.rb +159 -0
  46. data/spec/service_token_spec.rb +121 -0
  47. data/spec/spec_helper.rb +15 -0
  48. data/spec/transaction_spec.rb +71 -0
  49. data/spec/usagelimit_spec.rb +52 -0
  50. data/spec/user_spec.rb +164 -0
  51. data/spec/utilization_spec.rb +113 -0
  52. metadata +182 -0
@@ -0,0 +1,188 @@
1
+ require_relative './spec_helper'
2
+
3
+ module ThreeScale
4
+ module Core
5
+ describe Application do
6
+ describe '.load' do
7
+ describe 'with an existing application' do
8
+ before do
9
+ Application.delete(2001, 8011)
10
+ Application.save service_id: 2001, id: 8011, state: 'suspended',
11
+ plan_id: '3066', plan_name: 'crappy', redirect_url: 'blah'
12
+ end
13
+
14
+ it 'returns an Application object' do
15
+ Application.load(2001, 8011).class.must_equal Application
16
+ end
17
+
18
+ it 'parses data from received JSON' do
19
+ application = Application.load(2001, 8011)
20
+
21
+ application.service_id.must_equal '2001'
22
+ application.id.must_equal '8011'
23
+ application.state.must_equal 'suspended'
24
+ application.plan_id.must_equal '3066'
25
+ application.plan_name.must_equal 'crappy'
26
+ application.redirect_url.must_equal 'blah'
27
+ end
28
+ end
29
+
30
+ describe 'with a missing application' do
31
+ it 'returns nil' do
32
+ Application.load(2001, 7999).must_be_nil
33
+ end
34
+ end
35
+
36
+ describe 'with a missing service' do
37
+ it 'returns nil' do
38
+ Application.load(1999, 8011).must_be_nil
39
+ end
40
+ end
41
+
42
+ describe 'with both application and service missing' do
43
+ it 'returns nil' do
44
+ Application.load(1999, 7999).must_be_nil
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '.delete' do
50
+ before do
51
+ Application.delete(2001, 8011)
52
+ Application.save service_id: 2001, id: 8011, state: 'suspended',
53
+ plan_id: '3066', plan_name: 'crappy', redirect_url: 'blah'
54
+ end
55
+
56
+ describe 'with an existing application' do
57
+ it 'returns true when deleting an existing application' do
58
+ Application.delete(2001, 8011).must_equal true
59
+ end
60
+
61
+ it 'makes it non-existent' do
62
+ Application.delete(2001, 8011)
63
+ Application.load(2001, 8011).must_equal nil
64
+ end
65
+ end
66
+
67
+ describe 'with a non-existing application' do
68
+ it 'returns false when deleting an application with missing id' do
69
+ Application.delete(2001, 7999).must_equal false
70
+ end
71
+
72
+ it 'returns false when deleting an application with missing service id' do
73
+ Application.delete(1999, 8011).must_equal false
74
+ end
75
+ end
76
+ end
77
+
78
+ describe '.save' do
79
+ before do
80
+ Application.delete(2001, 8011)
81
+ @app = Application.save service_id: 2001, id: 8011, state: 'suspended',
82
+ plan_id: '3066', plan_name: 'crappy', redirect_url: 'blah'
83
+ end
84
+
85
+ it 'exists' do
86
+ Application.load(@app.service_id, @app.id).wont_be_nil
87
+ end
88
+
89
+ it 'returns an Application object' do
90
+ @app.must_be_kind_of Application
91
+ end
92
+
93
+ it 'returns an Application object with correct fields' do
94
+ @app.id.must_equal '8011'
95
+ @app.service_id.must_equal '2001'
96
+ @app.state.must_equal 'suspended'
97
+ @app.plan_id.must_equal '3066'
98
+ @app.plan_name.must_equal 'crappy'
99
+ @app.redirect_url.must_equal 'blah'
100
+ end
101
+
102
+ it 'modifies the application when saving an existing one' do
103
+ new_app = Application.save service_id: @app.service_id, id: @app.id, state: @app.state,
104
+ plan_id: @app.plan_id, plan_name: @app.plan_name, redirect_url: 'someurl'
105
+
106
+ new_app.id.must_equal(@app.id)
107
+ new_app.service_id.must_equal(@app.service_id)
108
+ new_app.state.must_equal(@app.state)
109
+ new_app.plan_id.must_equal(@app.plan_id)
110
+ new_app.plan_name.must_equal(@app.plan_name)
111
+ new_app.redirect_url.must_equal 'someurl'
112
+
113
+ reloaded_app = Application.load(@app.service_id, @app.id)
114
+
115
+ new_app.redirect_url.must_equal(reloaded_app.redirect_url)
116
+ end
117
+
118
+ it 'raises a client-side error when missing mandatory attributes' do
119
+ {service_id: 9000, foo: 'bar', bar: 'foo', id: 6077}.each_cons(2) do |attrs|
120
+ attrs = attrs.to_h
121
+ # note missing service_id, id
122
+ attrs.merge!(state: 'suspended', plan_id: '3066',
123
+ plan_name: 'crappy', redirect_url: 'blah')
124
+ lambda do
125
+ Application.save(attrs)
126
+ end.must_raise KeyError # minitest wont catch parent exceptions :/
127
+ end
128
+ end
129
+ end
130
+
131
+ describe '#save' do
132
+ before do
133
+ Application.delete(2001, 8011)
134
+ @app = Application.save service_id: 2001, id: 8011, state: 'suspended',
135
+ plan_id: '3066', plan_name: 'crappy', redirect_url: 'blah'
136
+ end
137
+
138
+ it 'exists' do
139
+ Application.load(@app.service_id, @app.id).wont_be_nil
140
+ end
141
+
142
+ it 'saves changes to an instance' do
143
+ @app.plan_name = 'some_other_plan'
144
+ @app.save
145
+ newapp = Application.load @app.service_id, @app.id
146
+
147
+ newapp.id.must_equal @app.id
148
+ newapp.service_id.must_equal @app.service_id
149
+ newapp.state.must_equal @app.state
150
+ newapp.plan_id.must_equal @app.plan_id
151
+ newapp.redirect_url.must_equal @app.redirect_url
152
+ newapp.plan_name.must_equal 'some_other_plan'
153
+ end
154
+
155
+ end
156
+
157
+ describe 'by_key' do
158
+ before do
159
+ Application.save_id_by_key(2001, 'a_key', 8011)
160
+ end
161
+
162
+ describe '.load_id_by_key' do
163
+ it 'returns the app ID linked to the specified service and key' do
164
+ Application.load_id_by_key(2001, 'a_key').must_equal '8011'
165
+ end
166
+ end
167
+
168
+ describe '.save_id_by_key' do
169
+ it 'changes the key linked to the app ID and service' do
170
+ Application.load_id_by_key(2001, 'another_key').must_be_nil
171
+ Application.save_id_by_key(2001, 'another_key', 8011).must_equal true
172
+ Application.load_id_by_key(2001, 'another_key').must_equal '8011'
173
+ # clean up this key
174
+ Application.delete_id_by_key(2001, 'another_key')
175
+ end
176
+ end
177
+
178
+ describe '.delete_id_by_key' do
179
+ it 'deletes the key linked to the app ID and service' do
180
+ Application.load_id_by_key(2001, 'a_key').must_equal '8011'
181
+ Application.delete_id_by_key(2001, 'a_key')
182
+ Application.load_id_by_key(2001, 'a_key').must_be_nil
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,82 @@
1
+ require_relative './spec_helper'
2
+ require_relative './private_endpoints/event'
3
+
4
+ module ThreeScale
5
+ module Core
6
+ describe Event do
7
+
8
+ let(:example_events) do
9
+ [{ type: 'first_traffic', object: { application_id: 1 } },
10
+ { type: 'first_daily_traffic', object: { application_id: 2 } },
11
+ { type: 'alert', object: { application_id: 3 } }]
12
+ end
13
+
14
+ before do
15
+ last_event = Event.load_all.last
16
+ Event.delete_upto(last_event.id) if last_event
17
+ end
18
+
19
+ describe '.load_all' do
20
+ before do
21
+ Event.save(example_events)
22
+ end
23
+
24
+ it 'returns a collection of Events' do
25
+ events = Event.load_all
26
+ events.size.must_equal example_events.size
27
+
28
+ events[0].type.must_equal example_events[0][:type]
29
+ events[0].object.must_equal example_events[0][:object]
30
+ events[0].timestamp.must_be_instance_of Time
31
+
32
+ events[1].type.must_equal example_events[1][:type]
33
+ events[1].object.must_equal example_events[1][:object]
34
+ events[1].timestamp.must_be_instance_of Time
35
+
36
+ events[2].type.must_equal example_events[2][:type]
37
+ events[2].object.must_equal example_events[2][:object]
38
+ events[2].timestamp.must_be_instance_of Time
39
+ end
40
+ end
41
+
42
+ describe '.delete' do
43
+ describe 'with an existing id event' do
44
+ before do
45
+ Event.save([example_events.first])
46
+ end
47
+
48
+ it 'returns true when deleting an existing event' do
49
+ Event.delete(Event.load_all.last.id).must_equal true
50
+ end
51
+ end
52
+
53
+ describe 'with a missing id event' do
54
+ # non_existing_id can be anything, because there are not any events
55
+ # saved at this point.
56
+ let(:non_existing_id) { 1000 }
57
+
58
+ it 'returns false when deleting an event with a non-existing id' do
59
+ Event.delete(non_existing_id).must_equal false
60
+ end
61
+ end
62
+ end
63
+
64
+ describe '.delete_upto' do
65
+ before do
66
+ Event.save(example_events)
67
+ end
68
+
69
+ let(:saved_events) { Event.load_all }
70
+
71
+ # Grab the ID of the event before the last one so we can delete all
72
+ # except one. Careful, this let will not work with if the number of
73
+ # saved events is less than 3.
74
+ let(:upto_id) { saved_events[saved_events.size - 2].id }
75
+
76
+ it 'returns the number of deleted events' do
77
+ Event.delete_upto(upto_id).must_equal example_events.size - 1
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,115 @@
1
+ require_relative './spec_helper'
2
+
3
+ module ThreeScale
4
+ module Core
5
+ describe Metric do
6
+ describe '.save' do
7
+ before do
8
+ Metric.delete(1001, 2001)
9
+ @metric = Metric.save(service_id: 1001, id: 2001, name: 'hits')
10
+ end
11
+
12
+ it 'exists' do
13
+ Metric.load(@metric.service_id, @metric.id).wont_be_nil
14
+ end
15
+
16
+ it 'returns a Metric object' do
17
+ @metric.must_be_kind_of Metric
18
+ end
19
+
20
+ it 'returns a Metric object with correct fields' do
21
+ @metric.service_id.must_equal '1001'
22
+ @metric.id.must_equal '2001'
23
+ @metric.name.must_equal 'hits'
24
+ @metric.parent_id.must_be_nil
25
+ end
26
+
27
+ it 'modifies a Metric when saving an existing one' do
28
+ new_metric = Metric.save(service_id: @metric.service_id, id: @metric.id, name: 'rqps')
29
+
30
+ new_metric.wont_be_nil
31
+ new_metric.id.must_equal(@metric.id)
32
+ new_metric.service_id.must_equal(@metric.service_id)
33
+ new_metric.name.wont_equal(@metric.name)
34
+ new_metric.name.must_equal 'rqps'
35
+
36
+ reloaded_metric = Metric.load(@metric.service_id, @metric.id)
37
+
38
+ reloaded_metric.wont_be_nil
39
+ new_metric.name.must_equal(reloaded_metric.name)
40
+ end
41
+
42
+ it 'raises a client-side error when missing mandatory attributes' do
43
+ {service_id: 9000, foo: 'bar', id: 6077}.each_cons(2) do |attrs|
44
+ attrs = attrs.to_h
45
+ # note missing service_id, id
46
+ attrs.merge!(name: 'somename')
47
+ lambda do
48
+ Metric.save(attrs)
49
+ end.must_raise KeyError # minitest wont catch parent exceptions :/
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '.load' do
55
+ before do
56
+ Metric.delete(1001, 2001)
57
+ Metric.save(service_id: 1001, id: 2001, name: 'hits')
58
+ end
59
+
60
+ it 'returns a Metric object' do
61
+ Metric.load(1001, 2001).class.must_equal Metric
62
+ end
63
+
64
+ it 'parses data from received JSON' do
65
+ metric = Metric.load(1001, 2001)
66
+
67
+ metric.wont_be_nil
68
+ metric.id.must_equal '2001'
69
+ metric.service_id.must_equal '1001'
70
+ metric.name.must_equal 'hits'
71
+ end
72
+
73
+ describe 'with a non-existing service id' do
74
+ it 'returns nil' do
75
+ Metric.load(7999, 2001).must_be_nil
76
+ end
77
+ end
78
+
79
+ describe 'with a non-existing id' do
80
+ it 'returns nil' do
81
+ Metric.load(1001, 7999).must_be_nil
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '.delete' do
87
+ before do
88
+ Metric.delete(1001, 2001)
89
+ Metric.save(service_id: 1001, id: 2001, name: 'hits')
90
+ end
91
+
92
+ describe 'with an existing metric' do
93
+ it 'returns true' do
94
+ Metric.delete(1001, 2001).must_equal true
95
+ end
96
+
97
+ it 'makes it non-existent' do
98
+ Metric.delete(1001, 2001)
99
+ Metric.load(1001, 2001).must_be_nil
100
+ end
101
+ end
102
+
103
+ describe 'with a non-existent metric' do
104
+ it 'returns false when using a non-existing service id' do
105
+ Metric.delete(7999, 2001).must_equal false
106
+ end
107
+
108
+ it 'returns false when using a non-existing metric id' do
109
+ Metric.delete(1001, 7999).must_equal false
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,9 @@
1
+ module PrivateEndpoints
2
+ module Event
3
+ def save(events)
4
+ api_create(events, { uri: default_uri, prefix: :events })
5
+ end
6
+ end
7
+ end
8
+
9
+ ThreeScale::Core::Event.extend PrivateEndpoints::Event
@@ -0,0 +1,10 @@
1
+ module PrivateEndpoints
2
+ module ServiceError
3
+ def save(service_id, errors)
4
+ api_create(
5
+ errors, { uri: service_errors_uri(service_id), prefix: :errors })
6
+ end
7
+ end
8
+ end
9
+
10
+ ThreeScale::Core::ServiceError.extend PrivateEndpoints::ServiceError
@@ -0,0 +1,16 @@
1
+ module PrivateEndpoints
2
+ module Transaction
3
+ def save(service_id, transactions)
4
+ api_create(transactions,
5
+ { uri: transactions_uri(service_id),
6
+ prefix: :transactions })
7
+ end
8
+
9
+ def delete_all(service_id)
10
+ api_delete({}, uri: transactions_uri(service_id))
11
+ end
12
+ end
13
+ end
14
+
15
+ ThreeScale::Core::Transaction.extend PrivateEndpoints::Transaction
16
+
@@ -0,0 +1,128 @@
1
+ require_relative './spec_helper'
2
+ require_relative './private_endpoints/service_error'
3
+
4
+ module ThreeScale
5
+ module Core
6
+ describe ServiceError do
7
+ let(:service_id) { '7575' }
8
+ let(:non_existing_service_id) { service_id.to_i.succ.to_s }
9
+
10
+ describe '.load_all' do
11
+ let(:error_messages) do
12
+ ["application with id=\"boo\" was not found",
13
+ "usage value \"lots\" for metric \"hits\" is invalid",
14
+ "metric \"foo\" is invalid",
15
+ "provider key \"test_app\" is invalid"]
16
+ end
17
+
18
+ before do
19
+ Service.delete_by_id!(service_id)
20
+ Service.save!(provider_key: 'foo', id: service_id)
21
+ ServiceError.delete_all(service_id)
22
+ ServiceError.save(service_id, error_messages)
23
+ end
24
+
25
+ describe 'without using pagination' do
26
+ it 'returns a collection with the correct size and a total' do
27
+ errors = ServiceError.load_all(service_id)
28
+ errors.size.must_equal error_messages.size
29
+ errors.total.must_equal error_messages.size
30
+ errors.map(&:message).must_equal error_messages.reverse
31
+ end
32
+ end
33
+
34
+ describe 'specifying page and per_page' do
35
+ let(:page) { 2 }
36
+ let(:per_page) { 2 }
37
+ let(:first_err_in_page) do
38
+ # Need to reverse because the last message to be saved is the first
39
+ # that we get when loading the messages
40
+ error_messages.reverse[per_page*(page - 1)]
41
+ end
42
+ let(:second_err_in_page) do
43
+ error_messages.reverse[per_page*(page - 1) + 1]
44
+ end
45
+
46
+ it 'returns per_page results and the errors of the page specified' do
47
+ service_errors = ServiceError.load_all(
48
+ service_id, { page: page, per_page: per_page })
49
+ service_errors.size.must_equal per_page
50
+ service_errors.total.must_equal error_messages.size
51
+
52
+ service_errors[0].message.must_equal first_err_in_page
53
+ service_errors[0].timestamp.must_be_instance_of Time
54
+ service_errors[1].message.must_equal second_err_in_page
55
+ service_errors[1].timestamp.must_be_instance_of Time
56
+ end
57
+ end
58
+
59
+ describe 'with a negative per-page value' do
60
+ let(:page) { 1 }
61
+ let(:per_page) { -1 }
62
+ it 'raises exception' do
63
+ lambda {
64
+ ServiceError.load_all(
65
+ service_id, { page: page, per_page: per_page })
66
+ }.must_raise InvalidPerPage
67
+ end
68
+ end
69
+
70
+ describe 'asking for an empty page' do
71
+ let(:page) { 2 }
72
+ let(:per_page) { error_messages.size }
73
+ it 'returns empty collection of errors and correct count' do
74
+ service_errors = ServiceError.load_all(
75
+ service_id, { page: page, per_page: per_page })
76
+
77
+ service_errors.size.must_equal 0
78
+ service_errors.total.must_equal error_messages.size
79
+ end
80
+ end
81
+
82
+ describe 'asking for the page that contains just the last error' do
83
+ let(:page) { 2 }
84
+ let(:per_page) { error_messages.size - 1 }
85
+ let(:oldest_error) { error_messages.reverse.last }
86
+
87
+ it 'returns one error and correct count' do
88
+ service_errors = ServiceError.load_all(
89
+ service_id, { page: page, per_page: per_page })
90
+
91
+ service_errors.size.must_equal 1
92
+ service_errors.total.must_equal error_messages.size
93
+
94
+ service_errors[0].message.must_equal oldest_error
95
+ service_errors[0].timestamp.must_be_instance_of Time
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '.delete_all' do
101
+ before do
102
+ Service.delete_by_id!(service_id)
103
+ Service.save!(provider_key: 'foo', id: service_id)
104
+ ServiceError.delete_all(service_id)
105
+ end
106
+
107
+ describe 'with an existing service' do
108
+ it 'returns true' do
109
+ ServiceError.delete_all(service_id).must_equal true
110
+ end
111
+
112
+ it 'deletes the errors' do
113
+ service_errors = ServiceError.load_all(service_id)
114
+
115
+ service_errors.must_be_empty
116
+ service_errors.total.must_equal 0
117
+ end
118
+ end
119
+
120
+ describe 'with a non-existing service' do
121
+ it 'returns false' do
122
+ ServiceError.delete_all(non_existing_service_id).must_equal false
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end