3scale_toolbox 0.17.1 → 0.18.0

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/3scale_toolbox.gemspec +1 -1
  3. data/README.md +6 -3
  4. data/lib/3scale_toolbox.rb +3 -0
  5. data/lib/3scale_toolbox/3scale_client_factory.rb +3 -4
  6. data/lib/3scale_toolbox/commands.rb +2 -0
  7. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_mapping_rules_task.rb +11 -27
  8. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_methods_task.rb +5 -10
  9. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_metrics_task.rb +4 -4
  10. data/lib/3scale_toolbox/commands/backend_command/copy_command/create_or_update_target_backend_task.rb +3 -2
  11. data/lib/3scale_toolbox/commands/backend_command/copy_command/task.rb +10 -32
  12. data/lib/3scale_toolbox/commands/import_command/issuer_type_transformer.rb +16 -0
  13. data/lib/3scale_toolbox/commands/import_command/openapi.rb +3 -0
  14. data/lib/3scale_toolbox/commands/import_command/openapi/create_mapping_rule_step.rb +2 -1
  15. data/lib/3scale_toolbox/commands/import_command/openapi/create_method_step.rb +3 -12
  16. data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +4 -0
  17. data/lib/3scale_toolbox/commands/import_command/openapi/update_service_proxy_step.rb +1 -0
  18. data/lib/3scale_toolbox/commands/methods_command/apply_command.rb +2 -4
  19. data/lib/3scale_toolbox/commands/methods_command/create_command.rb +0 -2
  20. data/lib/3scale_toolbox/commands/methods_command/delete_command.rb +1 -1
  21. data/lib/3scale_toolbox/commands/methods_command/list_command.rb +1 -9
  22. data/lib/3scale_toolbox/commands/metrics_command/list_command.rb +1 -1
  23. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_limits_step.rb +1 -1
  24. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_methods_step.rb +2 -2
  25. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_metrics_step.rb +2 -2
  26. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step.rb +1 -2
  27. data/lib/3scale_toolbox/commands/plans_command/export/step.rb +8 -20
  28. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_limits_step.rb +7 -8
  29. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_metrics_step.rb +6 -13
  30. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +8 -15
  31. data/lib/3scale_toolbox/commands/plans_command/import/step.rb +2 -22
  32. data/lib/3scale_toolbox/commands/plans_command/list_command.rb +1 -1
  33. data/lib/3scale_toolbox/commands/plans_command/show_command.rb +1 -1
  34. data/lib/3scale_toolbox/commands/policies_command.rb +24 -0
  35. data/lib/3scale_toolbox/commands/policies_command/export_command.rb +98 -0
  36. data/lib/3scale_toolbox/commands/policies_command/import_command.rb +61 -0
  37. data/lib/3scale_toolbox/commands/product_command.rb +4 -0
  38. data/lib/3scale_toolbox/commands/product_command/copy_command.rb +7 -3
  39. data/lib/3scale_toolbox/commands/product_command/copy_command/copy_backends_task.rb +22 -5
  40. data/lib/3scale_toolbox/commands/product_command/export_command.rb +81 -0
  41. data/lib/3scale_toolbox/commands/product_command/import_command.rb +125 -0
  42. data/lib/3scale_toolbox/commands/proxy_config_command.rb +2 -0
  43. data/lib/3scale_toolbox/commands/proxy_config_command/deploy_command.rb +54 -0
  44. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_activedocs_task.rb +15 -12
  45. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_app_plans_task.rb +15 -15
  46. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_limits_task.rb +12 -13
  47. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_mapping_rules_task.rb +11 -11
  48. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_methods_task.rb +8 -9
  49. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_metrics_task.rb +8 -8
  50. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_policies_task.rb +1 -1
  51. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_pricingrules_task.rb +15 -18
  52. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_service_proxy_task.rb +2 -2
  53. data/lib/3scale_toolbox/commands/service_command/copy_command/create_or_update_service_task.rb +2 -1
  54. data/lib/3scale_toolbox/commands/service_command/copy_command/destroy_mapping_rules_task.rb +9 -5
  55. data/lib/3scale_toolbox/commands/service_command/copy_command/task.rb +20 -34
  56. data/lib/3scale_toolbox/commands/update_command/service_command/delete_activedocs_task.rb +1 -3
  57. data/lib/3scale_toolbox/crds.rb +16 -0
  58. data/lib/3scale_toolbox/crds/application_plan_dump.rb +19 -0
  59. data/lib/3scale_toolbox/crds/backend_dump.rb +39 -0
  60. data/lib/3scale_toolbox/crds/backend_mapping_rule_dump.rb +26 -0
  61. data/lib/3scale_toolbox/crds/backend_method_dump.rb +12 -0
  62. data/lib/3scale_toolbox/crds/backend_metric_dump.rb +13 -0
  63. data/lib/3scale_toolbox/crds/backend_parser.rb +55 -0
  64. data/lib/3scale_toolbox/crds/backend_usage_dump.rb +11 -0
  65. data/lib/3scale_toolbox/crds/limit_dump.rb +37 -0
  66. data/lib/3scale_toolbox/crds/mapping_rule_dump.rb +26 -0
  67. data/lib/3scale_toolbox/crds/method_dump.rb +12 -0
  68. data/lib/3scale_toolbox/crds/metric_dump.rb +13 -0
  69. data/lib/3scale_toolbox/crds/pricing_rule_dump.rb +38 -0
  70. data/lib/3scale_toolbox/crds/product_deployment_parser.rb +329 -0
  71. data/lib/3scale_toolbox/crds/product_dump.rb +157 -0
  72. data/lib/3scale_toolbox/crds/product_parser.rb +114 -0
  73. data/lib/3scale_toolbox/crds/remote.rb +682 -0
  74. data/lib/3scale_toolbox/entities.rb +3 -0
  75. data/lib/3scale_toolbox/entities/activedocs.rb +12 -0
  76. data/lib/3scale_toolbox/entities/application_plan.rb +54 -46
  77. data/lib/3scale_toolbox/entities/backend.rb +65 -30
  78. data/lib/3scale_toolbox/entities/backend_mapping_rule.rb +29 -3
  79. data/lib/3scale_toolbox/entities/backend_method.rb +25 -16
  80. data/lib/3scale_toolbox/entities/backend_metric.rb +12 -2
  81. data/lib/3scale_toolbox/entities/backend_usage.rb +7 -1
  82. data/lib/3scale_toolbox/entities/limit.rb +71 -0
  83. data/lib/3scale_toolbox/entities/mapping_rule.rb +90 -0
  84. data/lib/3scale_toolbox/entities/method.rb +33 -19
  85. data/lib/3scale_toolbox/entities/metric.rb +29 -18
  86. data/lib/3scale_toolbox/entities/pricing_rule.rb +63 -0
  87. data/lib/3scale_toolbox/entities/proxy_config.rb +0 -1
  88. data/lib/3scale_toolbox/entities/service.rb +149 -46
  89. data/lib/3scale_toolbox/helper.rb +13 -16
  90. data/lib/3scale_toolbox/proxy_logger.rb +4 -0
  91. data/lib/3scale_toolbox/remote_cache.rb +157 -0
  92. data/lib/3scale_toolbox/remotes.rb +2 -2
  93. data/lib/3scale_toolbox/version.rb +1 -1
  94. data/licenses.xml +58 -50
  95. metadata +33 -6
@@ -1,6 +1,8 @@
1
1
  module ThreeScaleToolbox
2
2
  module Entities
3
3
  class BackendMetric
4
+ include CRD::BackendMetricSerializer
5
+
4
6
  VALID_PARAMS = %w[friendly_name system_name unit description].freeze
5
7
  public_constant :VALID_PARAMS
6
8
 
@@ -42,11 +44,19 @@ module ThreeScaleToolbox
42
44
  end
43
45
 
44
46
  def system_name
45
- @attrs['system_name']
47
+ attrs['system_name']
46
48
  end
47
49
 
48
50
  def friendly_name
49
- @attrs['friendly_name']
51
+ attrs['friendly_name']
52
+ end
53
+
54
+ def unit
55
+ attrs['unit']
56
+ end
57
+
58
+ def description
59
+ attrs['description']
50
60
  end
51
61
 
52
62
  def update(m_attrs)
@@ -3,6 +3,8 @@ module ThreeScaleToolbox
3
3
  ##
4
4
  # BackendUsage represents Product - Backend mapping entry
5
5
  class BackendUsage
6
+ include CRD::BackendUsageSerializer
7
+
6
8
  CREATE_PARAMS = %w[path backend_api_id].freeze
7
9
  public_constant :CREATE_PARAMS
8
10
  UPDATE_PARAMS = %w[path].freeze
@@ -54,7 +56,7 @@ module ThreeScaleToolbox
54
56
 
55
57
  def backend_id
56
58
  # 3scale API returns 'backend_id'
57
- # 3scale API only accepts 'backend_api_id' as params
59
+ # 3scale API only accepts 'backend_api_id' as params on create endpoint
58
60
  # good job
59
61
  attrs['backend_id']
60
62
  end
@@ -82,6 +84,10 @@ module ThreeScaleToolbox
82
84
  remote.delete_backend_usage product.id, id
83
85
  end
84
86
 
87
+ def backend
88
+ Backend.new(id: backend_id, remote: remote)
89
+ end
90
+
85
91
  private
86
92
 
87
93
  def fetch_attrs
@@ -0,0 +1,71 @@
1
+ module ThreeScaleToolbox
2
+ module Entities
3
+ class Limit
4
+ include CRD::Limit
5
+
6
+ class << self
7
+ def create(plan:, metric_id:, attrs:)
8
+ resp_attrs = plan.remote.create_application_plan_limit plan.id, metric_id, attrs
9
+ if (errors = resp_attrs['errors'])
10
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Limit has not been created', errors)
11
+ end
12
+
13
+ new(id: resp_attrs.fetch('id'), plan: plan, metric_id: metric_id, attrs: resp_attrs)
14
+ end
15
+ end
16
+
17
+ attr_reader :id, :plan, :remote, :attrs, :metric_id
18
+
19
+ def initialize(id:, plan:, metric_id:, attrs:)
20
+ @id = id.to_i
21
+ @plan = plan
22
+ @remote = plan.remote
23
+ @metric_id = metric_id
24
+ @attrs = attrs
25
+ end
26
+
27
+ def period
28
+ attrs['period']
29
+ end
30
+
31
+ def value
32
+ attrs['value']
33
+ end
34
+
35
+ def links
36
+ attrs['links'] || []
37
+ end
38
+
39
+ def metric_link
40
+ links.find { |link| link['rel'] == 'metric' }
41
+ end
42
+
43
+ def update(new_limit_attrs)
44
+ new_attrs = remote.update_application_plan_limit(plan.id, metric_id, id, new_limit_attrs)
45
+ if (errors = new_attrs['errors'])
46
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Limit has not been updated', errors)
47
+ end
48
+
49
+ # update current attrs
50
+ @attrs = new_attrs
51
+
52
+ new_attrs
53
+ end
54
+
55
+ def delete
56
+ remote.delete_application_plan_limit plan.id, metric_id, id
57
+ end
58
+
59
+ private
60
+
61
+ # Used by CRD::Limit
62
+ # Returns the backend hosting the metric
63
+ def backend_from_metric
64
+ backend_id = Helper.backend_metric_link_parser(metric_link['href'] || '')
65
+ return if backend_id.nil?
66
+
67
+ Backend.new(id: backend_id.to_i, remote: remote)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,90 @@
1
+ module ThreeScaleToolbox
2
+ module Entities
3
+ class MappingRule
4
+ include CRD::MappingRuleSerializer
5
+
6
+ VALID_PARAMS = %w[metric_id pattern http_method delta position last].freeze
7
+ public_constant :VALID_PARAMS
8
+
9
+ class << self
10
+ def create(service:, attrs:)
11
+ mapping_rule = service.remote.create_mapping_rule(
12
+ service.id,
13
+ Helper.filter_params(VALID_PARAMS, attrs)
14
+ )
15
+ if (errors = mapping_rule['errors'])
16
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('mapping rule has not been created',
17
+ errors)
18
+ end
19
+
20
+ new(id: mapping_rule.fetch('id'), service: service, attrs: mapping_rule)
21
+ end
22
+ end
23
+
24
+ attr_reader :id, :service, :remote
25
+
26
+ def initialize(id:, service:, attrs: nil)
27
+ @id = id.to_i
28
+ @service = service
29
+ @remote = service.remote
30
+ @attrs = attrs
31
+ end
32
+
33
+ def attrs
34
+ @attrs ||= mapping_rule_attrs
35
+ end
36
+
37
+ def http_method
38
+ attrs['http_method']
39
+ end
40
+
41
+ def pattern
42
+ attrs['pattern']
43
+ end
44
+
45
+ def delta
46
+ attrs['delta']
47
+ end
48
+
49
+ def last
50
+ attrs['last']
51
+ end
52
+
53
+ def metric_id
54
+ attrs['metric_id']
55
+ end
56
+
57
+ def update(mr_attrs)
58
+ new_attrs = remote.update_mapping_rule(
59
+ service.id, id,
60
+ Helper.filter_params(VALID_PARAMS, mr_attrs)
61
+ )
62
+ if (errors = new_attrs['errors'])
63
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Service mapping rule has not been updated', errors)
64
+ end
65
+
66
+ # update current attrs
67
+ @attrs = new_attrs
68
+
69
+ new_attrs
70
+ end
71
+
72
+ def delete
73
+ remote.delete_mapping_rule service.id, id
74
+ end
75
+
76
+ private
77
+
78
+ def mapping_rule_attrs
79
+ raise ThreeScaleToolbox::InvalidIdError if id.zero?
80
+
81
+ mapping_rule = remote.show_mapping_rule service.id, id
82
+ if (errors = mapping_rule['errors'])
83
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Service mapping rule not read', errors)
84
+ end
85
+
86
+ mapping_rule
87
+ end
88
+ end
89
+ end
90
+ end
@@ -1,38 +1,35 @@
1
1
  module ThreeScaleToolbox
2
2
  module Entities
3
3
  class Method
4
+ include CRD::MethodSerializer
5
+
4
6
  class << self
5
- def create(service:, parent_id:, attrs:)
6
- method = service.remote.create_method service.id, parent_id, attrs
7
- if (errors = method['errors'])
7
+ def create(service:, attrs:)
8
+ method_attrs = service.remote.create_method service.id, service.hits.id, attrs
9
+ if (errors = method_attrs['errors'])
8
10
  raise ThreeScaleToolbox::ThreeScaleApiError.new('Method has not been created', errors)
9
-
10
11
  end
11
12
 
12
- new(id: method.fetch('id'), parent_id: parent_id, service: service, attrs: method)
13
+ new(id: method_attrs.fetch('id'), service: service, attrs: method_attrs)
13
14
  end
14
15
 
15
16
  # ref can be system_name or method_id
16
- def find(service:, parent_id:, ref:)
17
- new(id: ref, parent_id: parent_id, service: service).tap(&:attrs)
17
+ def find(service:, ref:)
18
+ new(id: ref, service: service).tap(&:attrs)
18
19
  rescue ThreeScale::API::HttpClient::NotFoundError
19
- find_by_system_name(service: service, parent_id: parent_id, system_name: ref)
20
+ find_by_system_name(service: service, system_name: ref)
20
21
  end
21
22
 
22
- def find_by_system_name(service:, parent_id:, system_name:)
23
- method = service.methods(parent_id).find { |m| m['system_name'] == system_name }
24
- return if method.nil?
25
-
26
- new(id: method.fetch('id'), parent_id: parent_id, service: service, attrs: method)
23
+ def find_by_system_name(service:, system_name:)
24
+ service.methods.find { |m| m.system_name == system_name }
27
25
  end
28
26
  end
29
27
 
30
- attr_reader :id, :parent_id, :service, :remote
28
+ attr_reader :id, :service, :remote
31
29
 
32
- def initialize(id:, parent_id:, service:, attrs: nil)
30
+ def initialize(id:, service:, attrs: nil)
33
31
  @id = id.to_i
34
32
  @service = service
35
- @parent_id = parent_id
36
33
  @remote = service.remote
37
34
  @attrs = attrs
38
35
  end
@@ -41,6 +38,18 @@ module ThreeScaleToolbox
41
38
  @attrs ||= method_attrs
42
39
  end
43
40
 
41
+ def system_name
42
+ attrs['system_name']
43
+ end
44
+
45
+ def friendly_name
46
+ attrs['friendly_name']
47
+ end
48
+
49
+ def description
50
+ attrs['description']
51
+ end
52
+
44
53
  def disable
45
54
  Metric.new(id: id, service: service).disable
46
55
  end
@@ -50,7 +59,7 @@ module ThreeScaleToolbox
50
59
  end
51
60
 
52
61
  def update(m_attrs)
53
- new_attrs = remote.update_method(service.id, parent_id, id, m_attrs)
62
+ new_attrs = remote.update_method(service.id, hits_id, id, m_attrs)
54
63
  if (errors = new_attrs['errors'])
55
64
  raise ThreeScaleToolbox::ThreeScaleApiError.new('Method has not been updated', errors)
56
65
  end
@@ -62,13 +71,18 @@ module ThreeScaleToolbox
62
71
  end
63
72
 
64
73
  def delete
65
- remote.delete_method service.id, parent_id, id
74
+ remote.delete_method service.id, hits_id, id
66
75
  end
67
76
 
77
+
68
78
  private
69
79
 
80
+ def hits_id
81
+ service.hits.id
82
+ end
83
+
70
84
  def method_attrs
71
- method = remote.show_method service.id, parent_id, id
85
+ method = remote.show_method service.id, hits_id, id
72
86
  if (errors = method['errors'])
73
87
  raise ThreeScaleToolbox::ThreeScaleApiError.new('Method not read', errors)
74
88
  end
@@ -1,6 +1,8 @@
1
1
  module ThreeScaleToolbox
2
2
  module Entities
3
3
  class Metric
4
+ include CRD::MetricSerializer
5
+
4
6
  class << self
5
7
  def create(service:, attrs:)
6
8
  metric = service.remote.create_metric service.id, attrs
@@ -19,10 +21,7 @@ module ThreeScaleToolbox
19
21
  end
20
22
 
21
23
  def find_by_system_name(service:, system_name:)
22
- metric = service.metrics.find { |m| m['system_name'] == system_name }
23
- return if metric.nil?
24
-
25
- new(id: metric.fetch('id'), service: service, attrs: metric)
24
+ service.metrics.find { |m| m.system_name == system_name }
26
25
  end
27
26
  end
28
27
 
@@ -39,25 +38,41 @@ module ThreeScaleToolbox
39
38
  @attrs ||= metric_attrs
40
39
  end
41
40
 
41
+ def system_name
42
+ attrs['system_name']
43
+ end
44
+
45
+ def friendly_name
46
+ attrs['friendly_name']
47
+ end
48
+
49
+ def unit
50
+ attrs['unit']
51
+ end
52
+
53
+ def description
54
+ attrs['description']
55
+ end
56
+
42
57
  def disable
43
58
  # For each plan, get limits for the current metric
44
59
  # if already disabled -> NOOP
45
60
  # if non zero eternity limit exist, update
46
61
  # if non eternity limit exist, create
47
- service_plans.each do |plan|
62
+ service.plans.each do |plan|
48
63
  eternity_limit = plan_eternity_limit(plan)
49
64
  if eternity_limit.nil?
50
65
  plan.create_limit(id, zero_eternity_limit_attrs)
51
- elsif !eternity_limit.fetch('value').zero?
52
- plan.update_limit(id, eternity_limit.fetch('id'), zero_eternity_limit_attrs)
66
+ elsif !eternity_limit.value.zero?
67
+ eternity_limit.update(zero_eternity_limit_attrs)
53
68
  end
54
69
  end
55
70
  end
56
71
 
57
72
  def enable
58
- service_plans.each do |plan|
73
+ service.plans.each do |plan|
59
74
  limit = plan_zero_eternity_limit(plan)
60
- plan.delete_limit(id, limit.fetch('id')) unless limit.nil?
75
+ limit.delete unless limit.nil?
61
76
  end
62
77
  end
63
78
 
@@ -90,19 +105,15 @@ module ThreeScaleToolbox
90
105
 
91
106
  def plan_zero_eternity_limit(plan)
92
107
  # only one limit for eternity period is allowed per (plan_id, metric_id)
93
- plan.metric_limits(id).find { |limit| limit > zero_eternity_limit_attrs }
108
+ #plan.metric_limits(id).find { |limit| limit.attrs > zero_eternity_limit_attrs }
109
+ plan.metric_limits(id).find do |limit|
110
+ limit.attrs > zero_eternity_limit_attrs
111
+ end
94
112
  end
95
113
 
96
114
  def plan_eternity_limit(plan)
97
115
  # only one limit for eternity period is allowed per (plan_id, metric_id)
98
- plan.metric_limits(id).find { |limit| limit['period'] == 'eternity' }
99
- end
100
-
101
- def service_plans
102
- service.plans.map do |plan_attrs|
103
- ThreeScaleToolbox::Entities::ApplicationPlan.new(id: plan_attrs.fetch('id'),
104
- service: service)
105
- end
116
+ plan.metric_limits(id).find { |limit| limit.period == 'eternity' }
106
117
  end
107
118
 
108
119
  def zero_eternity_limit_attrs
@@ -0,0 +1,63 @@
1
+ module ThreeScaleToolbox
2
+ module Entities
3
+ class PricingRule
4
+ include CRD::PricingRuleSerializer
5
+
6
+ class << self
7
+ def create(plan:, metric_id:, attrs:)
8
+ resp_attrs = plan.remote.create_pricingrule plan.id, metric_id, attrs
9
+ if (errors = resp_attrs['errors'])
10
+ raise ThreeScaleToolbox::ThreeScaleApiError.new('Pricing rule has not been created', errors)
11
+ end
12
+
13
+ new(id: resp_attrs.fetch('id'), plan: plan, metric_id: metric_id, attrs: resp_attrs)
14
+ end
15
+ end
16
+
17
+ attr_reader :id, :plan, :remote, :attrs, :metric_id
18
+
19
+ def initialize(id:, plan:, metric_id:, attrs:)
20
+ @id = id.to_i
21
+ @plan = plan
22
+ @remote = plan.remote
23
+ @metric_id = metric_id
24
+ @attrs = attrs
25
+ end
26
+
27
+ def cost_per_unit
28
+ attrs['cost_per_unit'].to_f
29
+ end
30
+
31
+ def min
32
+ attrs['min']
33
+ end
34
+
35
+ def max
36
+ attrs['max']
37
+ end
38
+
39
+ def links
40
+ attrs['links'] || []
41
+ end
42
+
43
+ def metric_link
44
+ links.find { |link| link['rel'] == 'metric' }
45
+ end
46
+
47
+ def delete
48
+ remote.delete_application_plan_pricingrule plan.id, metric_id, id
49
+ end
50
+
51
+ private
52
+
53
+ # Used by CRD::PricingRule
54
+ # Returns the backend hosting the metric
55
+ def backend_from_metric
56
+ backend_id = Helper.backend_metric_link_parser(metric_link['href'] || '')
57
+ return if backend_id.nil?
58
+
59
+ Backend.new(id: backend_id.to_i, remote: remote)
60
+ end
61
+ end
62
+ end
63
+ end