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
@@ -6,9 +6,24 @@ module ThreeScaleToolbox
6
6
  include Task
7
7
 
8
8
  def call
9
- target.update_proxy source.proxy
9
+ target.update_proxy target_proxy_attrs
10
10
  target.update_oidc source.oidc if source.attrs['backend_version'] == 'oidc'
11
- puts "updated proxy of #{target.id} to match the original"
11
+ logger.info "updated proxy of #{target.id} to match the original"
12
+ end
13
+
14
+ def target_proxy_attrs
15
+ if source.attrs['deployment_option'] == 'hosted'
16
+ # For services with "hosted" deployment config,
17
+ # "Public Base URL" should not be copied, mainly because public base URL is self-assigned.
18
+ # Two 3scale products (aka services) cannot be served using the same public base URL.
19
+ source_proxy.dup.delete_if { |key, _v| %w[endpoint sandbox_endpoint].include? key }
20
+ else
21
+ source_proxy
22
+ end
23
+ end
24
+
25
+ def source_proxy
26
+ @source_proxy ||= source.proxy
12
27
  end
13
28
  end
14
29
  end
@@ -25,7 +25,8 @@ module ThreeScaleToolbox
25
25
  # assign target service for other tasks to have it available
26
26
  self.target = service
27
27
 
28
- puts "new service id #{service.id}"
28
+ logger.info "new service id #{service.id}"
29
+ report['product_id'] = service.id
29
30
  end
30
31
 
31
32
  private
@@ -12,10 +12,8 @@ module ThreeScaleToolbox
12
12
  def call
13
13
  return unless delete_mapping_rules
14
14
 
15
- puts 'destroying all mapping rules'
16
- target.mapping_rules.each do |mapping_rule|
17
- target.delete_mapping_rule mapping_rule['id']
18
- end
15
+ logger.info 'destroying all mapping rules'
16
+ target.mapping_rules.each(&:delete)
19
17
  end
20
18
 
21
19
  private
@@ -25,7 +23,13 @@ module ThreeScaleToolbox
25
23
  end
26
24
 
27
25
  def target
28
- context[:target]
26
+ context.fetch(:target)
27
+ end
28
+
29
+ def logger
30
+ context[:logger] ||= Logger.new($stdout).tap do |logger|
31
+ logger.formatter = proc { |severity, datetime, progname, msg| "#{msg}\n" }
32
+ end
29
33
  end
30
34
  end
31
35
  end
@@ -36,44 +36,12 @@ module ThreeScaleToolbox
36
36
  context[:delete_mapping_rules] = true
37
37
  end
38
38
 
39
- def source_metrics
40
- context[:source_metrics] ||= source.metrics
41
- end
42
-
43
- def source_hits
44
- context[:source_hits] ||= source.hits
45
- end
46
-
47
- def source_methods
48
- context[:source_methods] ||= source.methods(source_hits.fetch('id'))
49
- end
50
-
51
39
  def source_metrics_and_methods
52
- source_metrics + source_methods
53
- end
54
-
55
- def target_metrics
56
- context[:target_metrics] ||= target.metrics
57
- end
58
-
59
- def target_hits
60
- context[:target_hits] ||= target.hits
61
- end
62
-
63
- def target_methods
64
- context[:target_methods] ||= target.methods(target_hits.fetch('id'))
40
+ source.metrics + source.methods
65
41
  end
66
42
 
67
43
  def target_metrics_and_methods
68
- target_metrics + target_methods
69
- end
70
-
71
- def invalidate_target_methods
72
- context[:target_methods] = nil
73
- end
74
-
75
- def invalidate_target_metrics
76
- context[:target_metrics] = nil
44
+ target.metrics + target.methods
77
45
  end
78
46
 
79
47
  def source_remote
@@ -92,6 +60,24 @@ module ThreeScaleToolbox
92
60
  def option_target_system_name
93
61
  context[:option_target_system_name]
94
62
  end
63
+
64
+ def logger
65
+ context[:logger] ||= Logger.new($stdout).tap do |logger|
66
+ logger.formatter = proc { |severity, datetime, progname, msg| "#{msg}\n" }
67
+ end
68
+ end
69
+
70
+ def plans_report
71
+ report['application_plans'] ||= {}
72
+ end
73
+
74
+ def activedocs_report
75
+ report['activedocs'] ||= {}
76
+ end
77
+
78
+ def report
79
+ context[:report] ||= {}
80
+ end
95
81
  end
96
82
  end
97
83
  end
@@ -8,7 +8,7 @@ module ThreeScaleToolbox
8
8
  Cri::Command.define do
9
9
  name 'update'
10
10
  usage 'update <sub-command> [options]'
11
- summary '[DEPRECTATED] update super command'
11
+ summary '[DEPRECATED] update super command'
12
12
  description 'Update 3scale entities between tenants'
13
13
 
14
14
  run do |_opts, _args, cmd|
@@ -11,9 +11,9 @@ module ThreeScaleToolbox
11
11
  Cri::Command.define do
12
12
  name 'service'
13
13
  usage 'service [opts] -s <src> -d <dst> <src_service_id> <dst_service_id>'
14
- summary '[DEPRECTATED] update service'
14
+ summary '[DEPRECATED] update service'
15
15
  description <<-HEREDOC
16
- This command has been deprecated. Use '3scale copy service' instead.
16
+ This command has been deprecated. Use '3scale service copy' instead.
17
17
  \n Update existing service, update proxy settings, metrics, methods, application plans and mapping rules.'
18
18
  HEREDOC
19
19
 
@@ -30,6 +30,7 @@ module ThreeScaleToolbox
30
30
  end
31
31
 
32
32
  def run
33
+ warn "\e[1m\e[31mThis command has been deprecated. Use '3scale service copy' instead\e[0m"
33
34
  source_service = Entities::Service.new(
34
35
  id: arguments[:src_service_id],
35
36
  remote: threescale_client(fetch_required_option(:source))
@@ -11,9 +11,7 @@ module ThreeScaleToolbox
11
11
 
12
12
  def call
13
13
  puts 'deleting all target service ActiveDocs'
14
- target.activedocs.each do |activedoc|
15
- target.remote.delete_activedocs(activedoc['id'])
16
- end
14
+ target.activedocs.each(&:delete)
17
15
  end
18
16
 
19
17
  def target
@@ -0,0 +1,16 @@
1
+ require '3scale_toolbox/crds/application_plan_dump'
2
+ require '3scale_toolbox/crds/backend_method_dump'
3
+ require '3scale_toolbox/crds/backend_mapping_rule_dump'
4
+ require '3scale_toolbox/crds/backend_metric_dump'
5
+ require '3scale_toolbox/crds/backend_dump'
6
+ require '3scale_toolbox/crds/backend_usage_dump'
7
+ require '3scale_toolbox/crds/limit_dump'
8
+ require '3scale_toolbox/crds/mapping_rule_dump'
9
+ require '3scale_toolbox/crds/method_dump'
10
+ require '3scale_toolbox/crds/metric_dump'
11
+ require '3scale_toolbox/crds/pricing_rule_dump'
12
+ require '3scale_toolbox/crds/product_dump'
13
+ require '3scale_toolbox/crds/product_deployment_parser'
14
+ require '3scale_toolbox/crds/backend_parser'
15
+ require '3scale_toolbox/crds/product_parser'
16
+ require '3scale_toolbox/crds/remote'
@@ -0,0 +1,19 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ module ApplicationPlanSerializer
4
+ def to_cr
5
+ {
6
+ 'name' => name,
7
+ 'appsRequireApproval' => approval_required?,
8
+ 'trialPeriod' => trial_period_days,
9
+ 'setupFee' => setup_fee,
10
+ 'custom' => custom,
11
+ 'state' => state,
12
+ 'costMonth' => cost_per_month,
13
+ 'pricingRules' => pricing_rules.map(&:to_cr),
14
+ 'limits' => limits.map(&:to_cr)
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,39 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ module BackendSerializer
4
+ def to_cr
5
+ {
6
+ 'apiVersion' => 'capabilities.3scale.net/v1beta1',
7
+ 'kind' => 'Backend',
8
+ 'metadata' => {
9
+ 'annotations' => {
10
+ '3scale_toolbox_created_at' => Time.now.utc.iso8601,
11
+ '3scale_toolbox_version' => ThreeScaleToolbox::VERSION
12
+ },
13
+ 'name' => cr_name
14
+ },
15
+ 'spec' => {
16
+ 'name' => name,
17
+ 'systemName' => system_name,
18
+ 'privateBaseURL' => private_endpoint,
19
+ 'description' => description,
20
+ 'mappingRules' => mapping_rules.map(&:to_cr),
21
+ 'metrics' => metrics.each_with_object({}) do |metric, hash|
22
+ hash[metric.system_name] = metric.to_cr
23
+ end,
24
+ 'methods' => methods.each_with_object({}) do |method, hash|
25
+ hash[method.system_name] = method.to_cr
26
+ end
27
+ }
28
+ }
29
+ end
30
+
31
+ def cr_name
32
+ # Should be DNS1123 subdomain name
33
+ # TODO run validation for DNS1123
34
+ # https://kubernetes.io/docs/concepts/overview/working-with-objects/names/
35
+ "#{system_name.gsub(/[^[a-zA-Z0-9\-\.]]/, '.')}.#{Helper.random_lowercase_name}"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ module BackendMappingRuleSerializer
4
+ def to_cr
5
+ {
6
+ 'httpMethod' => http_method,
7
+ 'pattern' => pattern,
8
+ 'metricMethodRef' => metric_method_ref,
9
+ 'increment' => delta,
10
+ 'last' => last,
11
+ }
12
+ end
13
+
14
+ def metric_method_ref
15
+ if (method = backend.methods.find { |m| m.id == metric_id })
16
+ method.system_name
17
+ elsif (metric = backend.metrics.find { |m| m.id == metric_id })
18
+ metric.system_name
19
+ else
20
+ raise ThreeScaleToolbox::Error, "Unexpected error. Backend #{backend.system_name} " \
21
+ "mapping rule #{id} referencing to metric id #{metric_id} which has not been found"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ module BackendMethodSerializer
4
+ def to_cr
5
+ {
6
+ 'friendlyName' => friendly_name,
7
+ 'description' => description,
8
+ }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ module BackendMetricSerializer
4
+ def to_cr
5
+ {
6
+ 'friendlyName' => friendly_name,
7
+ 'unit' => unit,
8
+ 'description' => description,
9
+ }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ class BackendParser
4
+ Metric = Struct.new(:system_name, :friendly_name, :description, :unit)
5
+ Method = Struct.new(:system_name, :friendly_name, :description)
6
+ MappingRule = Struct.new(:metric_ref, :http_method, :pattern, :delta, :last)
7
+
8
+ attr_reader :cr
9
+
10
+ def initialize(cr)
11
+ @cr = cr
12
+ end
13
+
14
+ def system_name
15
+ cr.dig('spec', 'systemName')
16
+ end
17
+
18
+ def name
19
+ cr.dig('spec', 'name')
20
+ end
21
+
22
+ def description
23
+ cr.dig('spec', 'description')
24
+ end
25
+
26
+ def private_endpoint
27
+ cr.dig('spec', 'privateBaseURL')
28
+ end
29
+
30
+ def metrics
31
+ @metrics ||= (cr.dig('spec', 'metrics') || {}).map do |system_name, metric|
32
+ Metric.new(system_name, metric['friendlyName'], metric['description'], metric['unit'])
33
+ end
34
+ end
35
+
36
+ def methods
37
+ @methods ||= (cr.dig('spec', 'methods') || {}).map do |system_name, method|
38
+ Method.new(system_name, method['friendlyName'], method['description'])
39
+ end
40
+ end
41
+
42
+ def mapping_rules
43
+ @mapping_rules ||= (cr.dig('spec', 'mappingRules') || []).map do |mapping_rule|
44
+ MappingRule.new(mapping_rule['metricMethodRef'], mapping_rule['httpMethod'],
45
+ mapping_rule['pattern'], mapping_rule['increment'], mapping_rule['last'])
46
+ end
47
+ end
48
+
49
+ # Metrics and methods index by system_name
50
+ def metrics_index
51
+ @metrics_index ||= (methods + metrics).each_with_object({}) { |metric, h| h[metric.system_name] = metric }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,11 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ module BackendUsageSerializer
4
+ def to_cr
5
+ {
6
+ 'path' => path
7
+ }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ module Limit
4
+ def to_cr
5
+ {
6
+ 'period' => period,
7
+ 'value' => value,
8
+ 'metricMethodRef' => metric_system_name,
9
+ }
10
+ end
11
+
12
+ def metric_system_name
13
+ # Find in service methods
14
+ # Find in service metrics
15
+ # Find in backend methods
16
+ # Find in backend metrics
17
+ if (method = plan.service.methods.find { |m| m.id == metric_id })
18
+ { 'systemName' => method.system_name }
19
+ elsif (metric = plan.service.metrics.find { |m| m.id == metric_id })
20
+ { 'systemName' => metric.system_name }
21
+ elsif (backend = backend_from_metric)
22
+ if (backend_metric = backend.metrics.find { |m| m.id == metric_id })
23
+ { 'systemName' => backend_metric.system_name, 'backend' => backend.system_name }
24
+ elsif (backend_method = backend.methods.find { |m| m.id == metric_id })
25
+ { 'systemName' => backend_method.system_name, 'backend' => backend.system_name }
26
+ else
27
+ raise ThreeScaleToolbox::Error, "Unexpected error. Limit #{id} " \
28
+ "referencing to metric id #{metric_id} which has not been found"
29
+ end
30
+ else
31
+ raise ThreeScaleToolbox::Error, "Unexpected error. Limit #{id} " \
32
+ "referencing to metric id #{metric_id} which has not been found"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,26 @@
1
+ module ThreeScaleToolbox
2
+ module CRD
3
+ module MappingRuleSerializer
4
+ def to_cr
5
+ {
6
+ 'httpMethod' => http_method,
7
+ 'pattern' => pattern,
8
+ 'metricMethodRef' => metric_method_ref,
9
+ 'increment' => delta,
10
+ 'last' => last,
11
+ }
12
+ end
13
+
14
+ def metric_method_ref
15
+ if (method = service.methods.find { |m| m.id == metric_id })
16
+ method.system_name
17
+ elsif (metric = service.metrics.find { |m| m.id == metric_id })
18
+ metric.system_name
19
+ else
20
+ raise ThreeScaleToolbox::Error, "Unexpected error. Service #{service.system_name} " \
21
+ "mapping rule #{id} referencing to metric id #{metric_id} which has not been found"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end