pisoni 1.23.1

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.
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