3scale_toolbox 0.17.1 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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