3scale_toolbox 0.16.0 → 0.18.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/3scale_toolbox.gemspec +2 -2
  3. data/README.md +11 -8
  4. data/lib/3scale_toolbox.rb +3 -0
  5. data/lib/3scale_toolbox/3scale_client_factory.rb +3 -4
  6. data/lib/3scale_toolbox/cli/error_handler.rb +17 -14
  7. data/lib/3scale_toolbox/commands.rb +2 -0
  8. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_mapping_rules_task.rb +11 -27
  9. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_methods_task.rb +5 -10
  10. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_metrics_task.rb +4 -4
  11. data/lib/3scale_toolbox/commands/backend_command/copy_command/create_or_update_target_backend_task.rb +3 -2
  12. data/lib/3scale_toolbox/commands/backend_command/copy_command/task.rb +10 -32
  13. data/lib/3scale_toolbox/commands/import_command/issuer_type_transformer.rb +16 -0
  14. data/lib/3scale_toolbox/commands/import_command/openapi.rb +3 -0
  15. data/lib/3scale_toolbox/commands/import_command/openapi/create_activedocs_step.rb +3 -2
  16. data/lib/3scale_toolbox/commands/import_command/openapi/create_mapping_rule_step.rb +2 -1
  17. data/lib/3scale_toolbox/commands/import_command/openapi/create_method_step.rb +5 -14
  18. data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +4 -0
  19. data/lib/3scale_toolbox/commands/import_command/openapi/update_service_proxy_step.rb +1 -0
  20. data/lib/3scale_toolbox/commands/methods_command/apply_command.rb +2 -4
  21. data/lib/3scale_toolbox/commands/methods_command/create_command.rb +0 -2
  22. data/lib/3scale_toolbox/commands/methods_command/delete_command.rb +1 -1
  23. data/lib/3scale_toolbox/commands/methods_command/list_command.rb +1 -9
  24. data/lib/3scale_toolbox/commands/metrics_command/list_command.rb +1 -1
  25. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_limits_step.rb +1 -1
  26. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_methods_step.rb +2 -2
  27. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_metrics_step.rb +2 -2
  28. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step.rb +1 -2
  29. data/lib/3scale_toolbox/commands/plans_command/export/step.rb +8 -20
  30. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_limits_step.rb +12 -14
  31. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_metrics_step.rb +6 -13
  32. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +12 -20
  33. data/lib/3scale_toolbox/commands/plans_command/import/step.rb +2 -22
  34. data/lib/3scale_toolbox/commands/plans_command/list_command.rb +1 -1
  35. data/lib/3scale_toolbox/commands/plans_command/show_command.rb +1 -1
  36. data/lib/3scale_toolbox/commands/policies_command.rb +24 -0
  37. data/lib/3scale_toolbox/commands/policies_command/export_command.rb +98 -0
  38. data/lib/3scale_toolbox/commands/policies_command/import_command.rb +61 -0
  39. data/lib/3scale_toolbox/commands/product_command.rb +4 -0
  40. data/lib/3scale_toolbox/commands/product_command/copy_command.rb +7 -3
  41. data/lib/3scale_toolbox/commands/product_command/copy_command/copy_backends_task.rb +22 -5
  42. data/lib/3scale_toolbox/commands/product_command/export_command.rb +81 -0
  43. data/lib/3scale_toolbox/commands/product_command/import_command.rb +125 -0
  44. data/lib/3scale_toolbox/commands/proxy_config_command.rb +5 -0
  45. data/lib/3scale_toolbox/commands/proxy_config_command/deploy_command.rb +54 -0
  46. data/lib/3scale_toolbox/commands/proxy_config_command/export_command.rb +74 -0
  47. data/lib/3scale_toolbox/commands/proxy_config_command/helper.rb +15 -0
  48. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_activedocs_task.rb +15 -12
  49. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_app_plans_task.rb +15 -15
  50. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_limits_task.rb +12 -13
  51. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_mapping_rules_task.rb +11 -11
  52. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_methods_task.rb +9 -12
  53. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_metrics_task.rb +8 -8
  54. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_policies_task.rb +1 -1
  55. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_pricingrules_task.rb +15 -18
  56. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_service_proxy_task.rb +17 -2
  57. data/lib/3scale_toolbox/commands/service_command/copy_command/create_or_update_service_task.rb +2 -1
  58. data/lib/3scale_toolbox/commands/service_command/copy_command/destroy_mapping_rules_task.rb +9 -5
  59. data/lib/3scale_toolbox/commands/service_command/copy_command/task.rb +20 -34
  60. data/lib/3scale_toolbox/commands/update_command.rb +1 -1
  61. data/lib/3scale_toolbox/commands/update_command/service_command.rb +3 -2
  62. data/lib/3scale_toolbox/commands/update_command/service_command/delete_activedocs_task.rb +1 -3
  63. data/lib/3scale_toolbox/crds.rb +16 -0
  64. data/lib/3scale_toolbox/crds/application_plan_dump.rb +19 -0
  65. data/lib/3scale_toolbox/crds/backend_dump.rb +39 -0
  66. data/lib/3scale_toolbox/crds/backend_mapping_rule_dump.rb +26 -0
  67. data/lib/3scale_toolbox/crds/backend_method_dump.rb +12 -0
  68. data/lib/3scale_toolbox/crds/backend_metric_dump.rb +13 -0
  69. data/lib/3scale_toolbox/crds/backend_parser.rb +55 -0
  70. data/lib/3scale_toolbox/crds/backend_usage_dump.rb +11 -0
  71. data/lib/3scale_toolbox/crds/limit_dump.rb +37 -0
  72. data/lib/3scale_toolbox/crds/mapping_rule_dump.rb +26 -0
  73. data/lib/3scale_toolbox/crds/method_dump.rb +12 -0
  74. data/lib/3scale_toolbox/crds/metric_dump.rb +13 -0
  75. data/lib/3scale_toolbox/crds/pricing_rule_dump.rb +38 -0
  76. data/lib/3scale_toolbox/crds/product_deployment_parser.rb +329 -0
  77. data/lib/3scale_toolbox/crds/product_dump.rb +157 -0
  78. data/lib/3scale_toolbox/crds/product_parser.rb +114 -0
  79. data/lib/3scale_toolbox/crds/remote.rb +682 -0
  80. data/lib/3scale_toolbox/entities.rb +3 -0
  81. data/lib/3scale_toolbox/entities/activedocs.rb +12 -0
  82. data/lib/3scale_toolbox/entities/application_plan.rb +74 -39
  83. data/lib/3scale_toolbox/entities/backend.rb +65 -30
  84. data/lib/3scale_toolbox/entities/backend_mapping_rule.rb +29 -3
  85. data/lib/3scale_toolbox/entities/backend_method.rb +25 -16
  86. data/lib/3scale_toolbox/entities/backend_metric.rb +12 -2
  87. data/lib/3scale_toolbox/entities/backend_usage.rb +7 -1
  88. data/lib/3scale_toolbox/entities/limit.rb +71 -0
  89. data/lib/3scale_toolbox/entities/mapping_rule.rb +90 -0
  90. data/lib/3scale_toolbox/entities/method.rb +33 -19
  91. data/lib/3scale_toolbox/entities/metric.rb +29 -18
  92. data/lib/3scale_toolbox/entities/pricing_rule.rb +63 -0
  93. data/lib/3scale_toolbox/entities/proxy_config.rb +0 -1
  94. data/lib/3scale_toolbox/entities/service.rb +149 -46
  95. data/lib/3scale_toolbox/error.rb +50 -0
  96. data/lib/3scale_toolbox/helper.rb +13 -16
  97. data/lib/3scale_toolbox/openapi/oas3.rb +1 -1
  98. data/lib/3scale_toolbox/proxy_logger.rb +4 -0
  99. data/lib/3scale_toolbox/remote_cache.rb +157 -0
  100. data/lib/3scale_toolbox/remotes.rb +2 -2
  101. data/lib/3scale_toolbox/version.rb +1 -1
  102. data/licenses.xml +113 -45
  103. metadata +37 -8
@@ -52,7 +52,6 @@ module ThreeScaleToolbox
52
52
  end
53
53
  proxy_cfg
54
54
  end
55
-
56
55
  end
57
56
  end
58
57
  end
@@ -1,6 +1,8 @@
1
1
  module ThreeScaleToolbox
2
2
  module Entities
3
3
  class Service
4
+ include CRD::ProductSerializer
5
+
4
6
  VALID_PARAMS = %w[
5
7
  name backend_version deployment_option description
6
8
  system_name end_user_registration_required
@@ -29,16 +31,12 @@ module ThreeScaleToolbox
29
31
  end
30
32
 
31
33
  def find_by_system_name(remote:, system_name:)
32
- service_list = remote.list_services
33
-
34
- if service_list.respond_to?(:has_key?) && (errors = service_list['errors'])
35
- raise ThreeScaleToolbox::ThreeScaleApiError.new('Service list not read', errors)
34
+ attrs = list_services(remote: remote).find do |svc|
35
+ svc['system_name'] == system_name
36
36
  end
37
+ return if attrs.nil?
37
38
 
38
- service_attrs = service_list.find { |svc| svc['system_name'] == system_name }
39
- return if service_attrs.nil?
40
-
41
- new(id: service_attrs.fetch('id'), remote: remote, attrs: service_attrs)
39
+ new(id: attrs.fetch('id'), remote: remote, attrs: attrs)
42
40
  end
43
41
 
44
42
  private
@@ -61,6 +59,36 @@ module ThreeScaleToolbox
61
59
  def filtered_service_params(original_params)
62
60
  Helper.filter_params(VALID_PARAMS, original_params)
63
61
  end
62
+
63
+ def list_services(remote:)
64
+ services_enum(remote: remote).reduce([], :concat)
65
+ end
66
+
67
+ def services_enum(remote:)
68
+ Enumerator.new do |yielder|
69
+ page = 1
70
+ loop do
71
+ list = remote.list_services(
72
+ page: page,
73
+ per_page: ThreeScale::API::MAX_SERVICES_PER_PAGE
74
+ )
75
+
76
+ if list.respond_to?(:has_key?) && (errors = list['errors'])
77
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Service list not read', errors)
78
+ end
79
+
80
+ break if list.nil?
81
+
82
+ yielder << list
83
+
84
+ # The API response does not tell how many pages there are available
85
+ # If one page is not fully filled, it means that it is the last page.
86
+ break if list.length < ThreeScale::API::MAX_SERVICES_PER_PAGE
87
+
88
+ page += 1
89
+ end
90
+ end
91
+ end
64
92
  end
65
93
 
66
94
  attr_reader :id, :remote
@@ -75,6 +103,26 @@ module ThreeScaleToolbox
75
103
  @attrs ||= fetch_attrs
76
104
  end
77
105
 
106
+ def system_name
107
+ attrs['system_name']
108
+ end
109
+
110
+ def name
111
+ attrs['name']
112
+ end
113
+
114
+ def description
115
+ attrs['description']
116
+ end
117
+
118
+ def deployment_option
119
+ attrs['deployment_option']
120
+ end
121
+
122
+ def backend_version
123
+ attrs['backend_version']
124
+ end
125
+
78
126
  def update_proxy(proxy)
79
127
  new_proxy_attrs = remote.update_proxy id, proxy
80
128
 
@@ -94,37 +142,42 @@ module ThreeScaleToolbox
94
142
  proxy_attrs
95
143
  end
96
144
 
145
+ def cached_proxy
146
+ @cached_proxy ||= proxy
147
+ end
148
+
149
+ # @api public
150
+ # @return [List]
97
151
  def metrics
98
- # cache result to reuse
99
- metric_and_method_list = metrics_and_methods
100
- hits_metric_obj = hits_metric(metric_and_method_list)
101
- hits_id = hits_metric_obj.fetch('id')
152
+ metric_attr_list = metrics_and_methods.select { |metric_attrs| metric_attrs['parent_id'].nil? }
102
153
 
103
- ThreeScaleToolbox::Helper.array_difference(metric_and_method_list, methods(hits_id)) do |metric, method|
104
- ThreeScaleToolbox::Helper.compare_hashes(metric, method, %w[id])
154
+ metric_attr_list.map do |metric_attrs|
155
+ Metric.new(id: metric_attrs.fetch('id'), service: self, attrs: metric_attrs)
105
156
  end
106
157
  end
107
158
 
108
159
  def hits
109
- hits_metric(metrics_and_methods)
160
+ metric_list = metrics_and_methods.map do |metric_attrs|
161
+ Metric.new(id: metric_attrs.fetch('id'), service: self, attrs: metric_attrs)
162
+ end
163
+ metric_list.find { |metric| metric.system_name == 'hits' }.tap do |hits_metric|
164
+ raise ThreeScaleToolbox::Error, 'missing hits metric' if hits_metric.nil?
165
+ end
110
166
  end
111
167
 
112
- def methods(parent_metric_id)
113
- service_methods = remote.list_methods id, parent_metric_id
114
- if service_methods.respond_to?(:has_key?) && (errors = service_methods['errors'])
168
+ # @api public
169
+ # @return [List]
170
+ def methods
171
+ method_attr_list = remote.list_methods id, hits.id
172
+ if method_attr_list.respond_to?(:has_key?) && (errors = method_attr_list['errors'])
115
173
  raise ThreeScaleToolbox::ThreeScaleApiError.new('Service methods not read', errors)
116
174
  end
117
175
 
118
- service_methods
119
- end
120
-
121
- def metrics_and_methods
122
- m_m = remote.list_metrics id
123
- if m_m.respond_to?(:has_key?) && (errors = m_m['errors'])
124
- raise ThreeScaleToolbox::ThreeScaleApiError.new('Service metrics not read', errors)
176
+ method_attr_list.map do |method_attrs|
177
+ Method.new(id: method_attrs.fetch('id'),
178
+ service: self,
179
+ attrs: method_attrs)
125
180
  end
126
-
127
- m_m
128
181
  end
129
182
 
130
183
  def plans
@@ -133,19 +186,24 @@ module ThreeScaleToolbox
133
186
  raise ThreeScaleToolbox::ThreeScaleApiError.new('Service plans not read', errors)
134
187
  end
135
188
 
136
- service_plans
189
+ service_plans.map do |plan_attrs|
190
+ ApplicationPlan.new(id: plan_attrs.fetch('id'),
191
+ service: self,
192
+ attrs: plan_attrs)
193
+ end
137
194
  end
138
195
 
139
196
  def mapping_rules
140
- remote.list_mapping_rules id
141
- end
142
-
143
- def delete_mapping_rule(rule_id)
144
- remote.delete_mapping_rule(id, rule_id)
145
- end
197
+ mr_list = remote.list_mapping_rules id
198
+ if mr_list.respond_to?(:has_key?) && (errors = mr_list['errors'])
199
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Service mapping rules not read', errors)
200
+ end
146
201
 
147
- def create_mapping_rule(mapping_rule)
148
- remote.create_mapping_rule id, mapping_rule
202
+ mr_list.map do |mr_attrs|
203
+ MappingRule.new(id: mr_attrs.fetch('id'),
204
+ service: self,
205
+ attrs: mr_attrs)
206
+ end
149
207
  end
150
208
 
151
209
  def update(svc_attrs)
@@ -165,7 +223,12 @@ module ThreeScaleToolbox
165
223
  end
166
224
 
167
225
  def policies
168
- remote.show_policies id
226
+ policy_chain = remote.show_policies id
227
+ if policy_chain.respond_to?(:has_key?) && (errors = policy_chain['errors'])
228
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Service policies not read', errors)
229
+ end
230
+
231
+ policy_chain
169
232
  end
170
233
 
171
234
  def update_policies(params)
@@ -179,8 +242,12 @@ module ThreeScaleToolbox
179
242
  raise ThreeScaleToolbox::ThreeScaleApiError.new('Service activedocs not read', errors)
180
243
  end
181
244
 
182
- tenant_activedocs.select do |activedoc|
183
- activedoc['service_id'] == id
245
+ service_activedocs = tenant_activedocs.select do |activedoc_attrs|
246
+ activedoc_attrs['service_id'] == id
247
+ end
248
+
249
+ service_activedocs.map do |activedoc_attrs|
250
+ Entities::ActiveDocs.new(id: activedoc_attrs.fetch('id'), remote: remote, attrs: activedoc_attrs)
184
251
  end
185
252
  end
186
253
 
@@ -194,6 +261,10 @@ module ThreeScaleToolbox
194
261
  service_oidc
195
262
  end
196
263
 
264
+ def cached_oidc
265
+ @cached_oidc ||= oidc
266
+ end
267
+
197
268
  def update_oidc(oidc_settings)
198
269
  new_oidc = remote.update_oidc(id, oidc_settings)
199
270
 
@@ -262,19 +333,42 @@ module ThreeScaleToolbox
262
333
  end
263
334
  end
264
335
 
265
- def ==(other)
266
- remote.http_client.endpoint == other.remote.http_client.endpoint && id == other.id
336
+ def create_mapping_rule(mr_attrs)
337
+ Entities::MappingRule.create(service: self, attrs: mr_attrs)
267
338
  end
268
339
 
269
- private
340
+ def proxy_deploy
341
+ proxy_attrs = remote.proxy_deploy id
342
+ if proxy_attrs.respond_to?(:has_key?) && (errors = proxy_attrs['errors'])
343
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Proxy configuration not deployed', errors)
344
+ end
345
+
346
+ proxy_attrs
347
+ end
348
+
349
+ # Compute matrics mapping between products, including related backend metrics as well
350
+ def metrics_mapping(other)
351
+ mapping = (metrics + methods).product(other.metrics + other.methods).select do |m_a, m_b|
352
+ m_a.system_name == m_b.system_name
353
+ end.map { |m_a, m_b| [m_a.id, m_b.id] }.to_h
270
354
 
271
- def hits_metric(metric_list)
272
- hits_metric = metric_list.find { |metric| metric['system_name'] == 'hits' }
273
- raise ThreeScaleToolbox::Error, 'missing hits metric' if hits_metric.nil?
355
+ backend_pairs = backend_usage_list.map(&:backend).product(other.backend_usage_list.map(&:backend)).select do |b_a, b_b|
356
+ b_a.system_name == b_b.system_name
357
+ end
358
+
359
+ backend_pairs.each do |b_a, b_b|
360
+ mapping.merge!(b_a.metrics_mapping(b_b))
361
+ end
274
362
 
275
- hits_metric
363
+ mapping
276
364
  end
277
365
 
366
+ def ==(other)
367
+ remote.http_client.endpoint == other.remote.http_client.endpoint && id == other.id
368
+ end
369
+
370
+ private
371
+
278
372
  def fetch_attrs
279
373
  raise ThreeScaleToolbox::InvalidIdError if id.zero?
280
374
 
@@ -300,6 +394,15 @@ module ThreeScaleToolbox
300
394
 
301
395
  new_attrs
302
396
  end
397
+
398
+ def metrics_and_methods
399
+ m_m = remote.list_metrics id
400
+ if m_m.respond_to?(:has_key?) && (errors = m_m['errors'])
401
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Service metrics not read', errors)
402
+ end
403
+
404
+ m_m
405
+ end
303
406
  end
304
407
  end
305
408
  end
@@ -1,9 +1,24 @@
1
1
  module ThreeScaleToolbox
2
2
  # Generic error. Superclass for all specific errors.
3
3
  class Error < ::StandardError
4
+ def code
5
+ 'E_3SCALE'
6
+ end
7
+
8
+ def kind
9
+ self.class
10
+ end
11
+
12
+ def stacktrace
13
+ # For managed errors, stacktrace should not be necessary
14
+ nil
15
+ end
4
16
  end
5
17
 
6
18
  class InvalidUrlError < Error
19
+ def code
20
+ 'E_INVALID_URL'
21
+ end
7
22
  end
8
23
 
9
24
  class ActiveDocsNotFoundError < Error
@@ -12,6 +27,10 @@ module ThreeScaleToolbox
12
27
  def initialize(id)
13
28
  super("ActiveDocs with ID #{id} not found")
14
29
  end
30
+
31
+ def code
32
+ 'E_ACTIVEDOCS_NOT_FOUND'
33
+ end
15
34
  end
16
35
 
17
36
  class ThreeScaleApiError < Error
@@ -25,8 +44,39 @@ module ThreeScaleToolbox
25
44
  def message
26
45
  "#{super}. Errors: #{apierrors}"
27
46
  end
47
+
48
+ def code
49
+ 'E_3SCALE_API'
50
+ end
28
51
  end
29
52
 
30
53
  class InvalidIdError < Error
54
+ def code
55
+ 'E_INVALID_ID'
56
+ end
57
+ end
58
+
59
+ class UnexpectedError < ::StandardError
60
+ attr_reader :unexpectederror
61
+
62
+ def initialize(err)
63
+ @unexpectederror = err
64
+ end
65
+
66
+ def message
67
+ unexpectederror.message
68
+ end
69
+
70
+ def kind
71
+ unexpectederror.class
72
+ end
73
+
74
+ def code
75
+ 'E_UNKNOWN'
76
+ end
77
+
78
+ def stacktrace
79
+ unexpectederror.backtrace
80
+ end
31
81
  end
32
82
  end
@@ -51,24 +51,21 @@ module ThreeScaleToolbox
51
51
  Array(Hash(error)['period']).any? { |msg| msg.match(/has already been taken/) }
52
52
  end
53
53
 
54
- def metrics_mapping(source_metrics, target_metrics)
55
- target_metrics.map do |target|
56
- source = source_metrics.find do |m|
57
- compare_hashes(m, target, ['system_name'])
58
- end || {}
59
-
60
- [source['id'], target['id']]
61
- end.to_h
54
+ def application_plan_mapping(source_app_plans, target_app_plans)
55
+ target_app_plans.map do |target|
56
+ source = source_app_plans.find { |app_plan| app_plan.system_name == target.system_name }
57
+ [source, target]
58
+ end.reject { |key, _| key.nil? }
62
59
  end
63
60
 
64
- def application_plan_mapping(source_app_plans, target_app_plans)
65
- mapping = target_app_plans.map do |target|
66
- source = source_app_plans.find do |app_plan|
67
- compare_hashes(app_plan, target, ['system_name'])
68
- end || {}
69
- [source['id'], target]
70
- end
71
- mapping.reject { |key, _| key.nil? }
61
+ def random_lowercase_name(length=8)
62
+ [*('a'..'z')].sample(length).join
63
+ end
64
+
65
+ def backend_metric_link_parser(link)
66
+ return if link.nil?
67
+
68
+ link.match(/admin\/api\/backend_apis\/(\d+)\/metrics/) { |m| m.captures[0] }
72
69
  end
73
70
  end
74
71
 
@@ -64,7 +64,7 @@ module ThreeScaleToolbox
64
64
 
65
65
  def host
66
66
  # If there are many? take first
67
- server_objects(&:host).first
67
+ server_objects { |url| "#{url.host}:#{url.port}" }.first
68
68
  end
69
69
 
70
70
  def scheme
@@ -13,6 +13,10 @@ module ThreeScaleToolbox
13
13
  result
14
14
  end
15
15
 
16
+ def public_send(name, *args)
17
+ method_missing(name, *args)
18
+ end
19
+
16
20
  def respond_to_missing?(method_name, include_private = false)
17
21
  super
18
22
  end
@@ -0,0 +1,157 @@
1
+ module ThreeScaleToolbox
2
+ class RemoteCache < BasicObject
3
+
4
+ attr_reader :metrics_cache, :methods_cache, :backend_metrics_cache, :backend_methods_cache, :subject
5
+
6
+ def initialize(subject)
7
+ @subject = subject
8
+ # Metrics and methods cache data
9
+ @metrics_cache = {}
10
+ # methods cache data
11
+ @methods_cache = {}
12
+ # Backend Metrics and methods cache data
13
+ @backend_metrics_cache = {}
14
+ # Backend methods cache data
15
+ @backend_methods_cache = {}
16
+ end
17
+
18
+ def list_metrics(service_id)
19
+ return metrics_cache[service_id] if metrics_cache.has_key? service_id
20
+
21
+ subject.list_metrics(service_id).tap do |metrics|
22
+ metrics_cache[service_id] = metrics unless metrics.respond_to?(:has_key?) && !metrics['errors'].nil?
23
+ end
24
+ end
25
+
26
+ def list_methods(service_id, metric_id)
27
+ key = method_cache_key(service_id, metric_id)
28
+ return methods_cache[key] if methods_cache.has_key? key
29
+
30
+ subject.list_methods(service_id, metric_id).tap do |methods|
31
+ methods_cache[key] = methods unless methods.respond_to?(:has_key?) && !methods['errors'].nil?
32
+ end
33
+ end
34
+
35
+ def create_metric(service_id, attributes)
36
+ subject.create_metric(service_id, attributes).tap do |metric_attrs|
37
+ metrics_cache.delete(service_id) unless metric_attrs.respond_to?(:has_key?) && !metric_attrs['errors'].nil?
38
+ end
39
+ end
40
+
41
+ def update_metric(service_id, metric_id, attributes)
42
+ subject.update_metric(service_id, metric_id, attributes).tap do |metric_attrs|
43
+ metrics_cache.delete(service_id) unless metric_attrs.respond_to?(:has_key?) && !metric_attrs['errors'].nil?
44
+ end
45
+ end
46
+
47
+ def delete_metric(service_id, metric_id)
48
+ subject.delete_metric(service_id, metric_id).tap do |_|
49
+ metrics_cache.delete(service_id)
50
+ end
51
+ end
52
+
53
+ def update_method(service_id, parent_id, id, attributes)
54
+ subject.update_method(service_id, parent_id, id, attributes).tap do |method_attrs|
55
+ metrics_cache.delete(service_id) unless method_attrs.respond_to?(:has_key?) && !method_attrs['errors'].nil?
56
+ methods_cache.delete(method_cache_key(service_id, parent_id)) unless method_attrs.respond_to?(:has_key?) && !method_attrs['errors'].nil?
57
+ end
58
+ end
59
+
60
+
61
+ def create_method(service_id, metric_id, attributes)
62
+ subject.create_method(service_id, metric_id, attributes).tap do |method_attrs|
63
+ metrics_cache.delete(service_id) unless method_attrs.respond_to?(:has_key?) && !method_attrs['errors'].nil?
64
+ methods_cache.delete(method_cache_key(service_id, metric_id)) unless method_attrs.respond_to?(:has_key?) && !method_attrs['errors'].nil?
65
+ end
66
+ end
67
+
68
+ def delete_method(service_id, parent_id, id)
69
+ subject.delete_method(service_id, parent_id, id).tap do |_|
70
+ metrics_cache.delete(service_id)
71
+ methods_cache.delete(method_cache_key(service_id, parent_id))
72
+ end
73
+ end
74
+
75
+ ###
76
+ # Backends
77
+ ###
78
+
79
+ def list_backend_metrics(backend_id)
80
+ return backend_metrics_cache[backend_id] if backend_metrics_cache.has_key? backend_id
81
+
82
+ subject.list_backend_metrics(backend_id).tap do |metrics|
83
+ backend_metrics_cache[backend_id] = metrics unless metrics.respond_to?(:has_key?) && !metrics['errors'].nil?
84
+ end
85
+ end
86
+
87
+ def list_backend_methods(backend_id, metric_id)
88
+ key = method_cache_key(backend_id, metric_id)
89
+ return backend_methods_cache[key] if backend_methods_cache.has_key? key
90
+
91
+ subject.list_backend_methods(backend_id, metric_id).tap do |methods|
92
+ backend_methods_cache[key] = methods unless methods.respond_to?(:has_key?) && !methods['errors'].nil?
93
+ end
94
+ end
95
+
96
+ def create_backend_metric(backend_id, attributes)
97
+ subject.create_backend_metric(backend_id, attributes).tap do |metric_attrs|
98
+ backend_metrics_cache.delete(backend_id) unless metric_attrs.respond_to?(:has_key?) && !metric_attrs['errors'].nil?
99
+ end
100
+ end
101
+
102
+ def update_backend_metric(backend_id, metric_id, attributes)
103
+ subject.update_backend_metric(backend_id, metric_id, attributes).tap do |metric_attrs|
104
+ backend_metrics_cache.delete(backend_id) unless metric_attrs.respond_to?(:has_key?) && !metric_attrs['errors'].nil?
105
+ end
106
+ end
107
+
108
+ def delete_backend_metric(backend_id, metric_id)
109
+ subject.delete_backend_metric(backend_id, metric_id).tap do |_|
110
+ backend_metrics_cache.delete(backend_id)
111
+ end
112
+ end
113
+
114
+ def create_backend_method(backend_id, metric_id, attributes)
115
+ subject.create_backend_method(backend_id, metric_id, attributes).tap do |method_attrs|
116
+ unless method_attrs.respond_to?(:has_key?) && !method_attrs['errors'].nil?
117
+ backend_metrics_cache.delete(backend_id)
118
+ backend_methods_cache.delete(method_cache_key(backend_id, metric_id))
119
+ end
120
+ end
121
+ end
122
+
123
+ def delete_backend_method(backend_id, metric_id, method_id)
124
+ subject.delete_backend_method(backend_id, metric_id, method_id).tap do |_|
125
+ backend_metrics_cache.delete(backend_id)
126
+ backend_methods_cache.delete(method_cache_key(backend_id, metric_id))
127
+ end
128
+ end
129
+
130
+ def update_backend_method(backend_id, metric_id, method_id, attributes)
131
+ subject.update_backend_method(backend_id, metric_id, method_id, attributes).tap do |method_attrs|
132
+ unless method_attrs.respond_to?(:has_key?) && !method_attrs['errors'].nil?
133
+ backend_metrics_cache.delete(backend_id)
134
+ backend_methods_cache.delete(method_cache_key(backend_id, metric_id))
135
+ end
136
+ end
137
+ end
138
+
139
+ ###
140
+ # Generic methods
141
+ ###
142
+
143
+ def method_missing(name, *args)
144
+ subject.public_send(name, *args)
145
+ end
146
+
147
+ def respond_to_missing?(method_name, include_private = false)
148
+ super
149
+ end
150
+
151
+ private
152
+
153
+ def method_cache_key(id, metric_id)
154
+ "#{id}#{metric_id}"
155
+ end
156
+ end
157
+ end