3scale_toolbox 0.18.3 → 0.19.3

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/3scale_toolbox.gemspec +3 -3
  3. data/README.md +1 -2
  4. data/lib/3scale_toolbox/commands/backend_command/copy_command/delete_mapping_rules_task.rb +18 -0
  5. data/lib/3scale_toolbox/commands/backend_command/copy_command/task.rb +4 -0
  6. data/lib/3scale_toolbox/commands/backend_command/copy_command.rb +4 -1
  7. data/lib/3scale_toolbox/commands/import_command/import_csv.rb +8 -8
  8. data/lib/3scale_toolbox/commands/import_command/openapi/create_activedocs_step.rb +1 -1
  9. data/lib/3scale_toolbox/commands/import_command/openapi/update_policies_step.rb +23 -10
  10. data/lib/3scale_toolbox/commands/import_command/openapi.rb +2 -0
  11. data/lib/3scale_toolbox/commands/plans_command/export_command.rb +52 -29
  12. data/lib/3scale_toolbox/commands/plans_command/import/import_backend_metrics_step.rb +37 -0
  13. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_limits_step.rb +11 -2
  14. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_metrics_step.rb +2 -2
  15. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +12 -1
  16. data/lib/3scale_toolbox/commands/plans_command/import/step.rb +23 -8
  17. data/lib/3scale_toolbox/commands/plans_command/import/validate_plan_step.rb +126 -0
  18. data/lib/3scale_toolbox/commands/plans_command/import_command.rb +5 -1
  19. data/lib/3scale_toolbox/commands/product_command/copy_command/copy_backends_task.rb +6 -0
  20. data/lib/3scale_toolbox/commands/product_command/copy_command.rb +3 -2
  21. data/lib/3scale_toolbox/commands/product_command/import_command.rb +1 -0
  22. data/lib/3scale_toolbox/crds/limit_dump.rb +1 -1
  23. data/lib/3scale_toolbox/crds/pricing_rule_dump.rb +1 -1
  24. data/lib/3scale_toolbox/entities/application_plan.rb +64 -0
  25. data/lib/3scale_toolbox/entities/backend.rb +4 -0
  26. data/lib/3scale_toolbox/entities/backend_method.rb +16 -0
  27. data/lib/3scale_toolbox/entities/backend_metric.rb +16 -0
  28. data/lib/3scale_toolbox/entities/limit.rb +52 -7
  29. data/lib/3scale_toolbox/entities/method.rb +11 -0
  30. data/lib/3scale_toolbox/entities/metric.rb +12 -0
  31. data/lib/3scale_toolbox/entities/pricing_rule.rb +52 -7
  32. data/lib/3scale_toolbox/entities/service.rb +4 -0
  33. data/lib/3scale_toolbox/proxy_logger.rb +2 -0
  34. data/lib/3scale_toolbox/remote_cache.rb +49 -2
  35. data/lib/3scale_toolbox/version.rb +1 -1
  36. data/licenses.xml +15 -25
  37. metadata +8 -13
  38. data/lib/3scale_toolbox/commands/plans_command/export/read_app_plan_step.rb +0 -16
  39. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_features_step.rb +0 -16
  40. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_limits_step.rb +0 -19
  41. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_methods_step.rb +0 -47
  42. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_metrics_step.rb +0 -47
  43. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step.rb +0 -19
  44. data/lib/3scale_toolbox/commands/plans_command/export/step.rb +0 -85
  45. data/lib/3scale_toolbox/commands/plans_command/export/write_artifacts_file_step.rb +0 -84
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a3084c0b2b684a252c7e07c4c9a87e3087ada1ad6a677766aa508ac98e1f313
4
- data.tar.gz: 158b1b008a67836c2b27ccd8cbcd49f59995e4ac776eae93c59bf44b002cbf3a
3
+ metadata.gz: d2a44bdf128bf6f8d4d0a592a4eee49c82c34415017e03366ff2bcc241fe18c0
4
+ data.tar.gz: 0e94df4747331e9092ae0c961709cfcc334a553eb54209378941b8239307eceb
5
5
  SHA512:
6
- metadata.gz: '02789c23291a2191617a56c3456297539b09e0922bbf62b57b613065b04d8951800d91f49989d510258c0c3b1baa308d1219f4c29373879c8a65f9a93bd4653a'
7
- data.tar.gz: abaca7089c51b5de57c118f5154a74466dd6671a96d7ec043b47ba0d4772761a2d9896b1195e762115ff121296c16cc2f195a5d39e9c20191393f45e6ee756bc
6
+ metadata.gz: 8dd7a6efc6567598d87e4ebbc18c486eba1ea9e6766ca6c0241f78e73a4287408d9e18ac838788e81a073c8f3a8fd93d299fac4ea9f21a42571e3cff68f2b0bb
7
+ data.tar.gz: c4ed75a0b46414606208a5fb6e1374e72d5fe06fbb5a237b3793bc2471d20667c489acace51cdf93d4971bfe59b42dc2919631b90074a8af72bac1668c663d01
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.name = '3scale_toolbox'
9
9
  spec.version = ThreeScaleToolbox::VERSION
10
10
  spec.licenses = ['MIT']
11
- spec.authors = ['Michal Cichra', 'Eguzki Astiz Lezaun']
12
- spec.email = ['michal@3scale.net', 'eastizle@redhat.com']
11
+ spec.authors = ['Miguel Soriano', 'Eguzki Astiz Lezaun']
12
+ spec.email = ['msoriano@redhat.com', 'eastizle@redhat.com']
13
13
 
14
14
  spec.summary = %q{3scale Toolbox.}
15
15
  spec.description = %q{3scale tools to manage your API from the terminal.}
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency 'rake', '~> 13.0'
35
35
  spec.add_development_dependency 'rspec', '~> 3.8'
36
36
  spec.add_development_dependency 'webmock', '~> 3.4'
37
- spec.required_ruby_version = '>= 2.5'
37
+ spec.required_ruby_version = '>= 2.6'
38
38
 
39
39
  spec.add_dependency '3scale-api', '~> 1.4'
40
40
  spec.add_dependency 'cri', '~> 2.15'
data/README.md CHANGED
@@ -39,7 +39,6 @@
39
39
  ## Requirements
40
40
  Supported Ruby interpreters
41
41
 
42
- * MRI 2.5
43
42
  * MRI 2.6
44
43
  * MRI 2.7
45
44
 
@@ -219,5 +218,5 @@ Install, uninstall and update plugins using tools like [RubyGems](https://guides
219
218
 
220
219
  ## Contributing
221
220
 
222
- Bug reports and pull requests are welcome on GitHub at https://github.com/3scale/3scale_toolbox.
221
+ If you are interested in contributing to 3scale Toolbox, please refer to instructions available [here](docs/contributing.md)
223
222
 
@@ -0,0 +1,18 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module BackendCommand
4
+ module CopyCommand
5
+ class DeleteMappingRulesTask
6
+ include Task
7
+
8
+ # entrypoint
9
+ def run
10
+ return unless delete_mapping_rules
11
+
12
+ target_backend.mapping_rules.each(&:delete)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -53,6 +53,10 @@ module ThreeScaleToolbox
53
53
  context[:report] ||= {}
54
54
  end
55
55
 
56
+ def delete_mapping_rules
57
+ context.fetch(:delete_mapping_rules, false)
58
+ end
59
+
56
60
  private
57
61
 
58
62
  def find_source_backend
@@ -2,6 +2,7 @@ require '3scale_toolbox/commands/backend_command/copy_command/task'
2
2
  require '3scale_toolbox/commands/backend_command/copy_command/create_or_update_target_backend_task'
3
3
  require '3scale_toolbox/commands/backend_command/copy_command/copy_metrics_task'
4
4
  require '3scale_toolbox/commands/backend_command/copy_command/copy_methods_task'
5
+ require '3scale_toolbox/commands/backend_command/copy_command/delete_mapping_rules_task'
5
6
  require '3scale_toolbox/commands/backend_command/copy_command/copy_mapping_rules_task'
6
7
 
7
8
  module ThreeScaleToolbox
@@ -17,7 +18,7 @@ module ThreeScaleToolbox
17
18
  summary 'Copy backend'
18
19
  description <<-HEREDOC
19
20
  This command makes a copy of the referenced backend.
20
- Target backend will be searched by source backend system name. System name can be overriden with `--target-system-name` option.
21
+ Target backend will be searched by the source backend system name. System name can be overridden with `--target-system-name` option.
21
22
  If a backend with the selected `system-name` is not found, it will be created.
22
23
  \n Components of the backend being copied:
23
24
  \nmetrics
@@ -41,6 +42,7 @@ module ThreeScaleToolbox
41
42
  # First metrics as methods need 'hits' metric in target backend
42
43
  tasks << CopyCommand::CopyMetricsTask.new(context)
43
44
  tasks << CopyCommand::CopyMethodsTask.new(context)
45
+ tasks << CopyCommand::DeleteMappingRulesTask.new(context)
44
46
  tasks << CopyCommand::CopyMappingRulesTask.new(context)
45
47
  tasks.each(&:call)
46
48
  end
@@ -56,6 +58,7 @@ module ThreeScaleToolbox
56
58
  source_remote: threescale_client(fetch_required_option(:source)),
57
59
  target_remote: threescale_client(fetch_required_option(:destination)),
58
60
  source_backend_ref: arguments[:source_backend],
61
+ delete_mapping_rules: true,
59
62
  option_target_system_name: options[:'target-system-name']
60
63
  }
61
64
  end
@@ -104,14 +104,14 @@ module ThreeScaleToolbox
104
104
 
105
105
  # create a mapping rule
106
106
  if (metric_id = metric['id'] || method['id'])
107
- mapping_rule = client.create_mapping_rule(service['id'], {
108
- metric_id: metric_id,
109
- pattern: item['endpoint_path'],
110
- http_method: item['endpoint_http_method'],
111
- metric_system_name: item['endpoint_system_name'],
112
- auth_app_key: auth_app_key_according_service(service),
113
- delta: 1
114
- })
107
+ mapping_rule = client.create_mapping_rule(service['id'],{
108
+ metric_id: metric_id,
109
+ pattern: item['endpoint_path'],
110
+ http_method: item['endpoint_http_method'],
111
+ metric_system_name: item['endpoint_system_name'],
112
+ auth_app_key: auth_app_key_according_service(service),
113
+ delta: 1
114
+ })
115
115
 
116
116
  if mapping_rule['errors'].nil?
117
117
  stats[:mapping_rules] += 1
@@ -53,7 +53,7 @@ module ThreeScaleToolbox
53
53
  # Other processing steps can work with original openapi spec
54
54
  Helper.hash_deep_dup(resource).tap do |activedocs|
55
55
  # public production base URL
56
- # the basePath field is updated to a new value only when overriden by optional param
56
+ # the basePath field is updated to a new value only when overridden by optional param
57
57
  unless service.proxy['endpoint'].nil?
58
58
  api_spec.set_server_url(activedocs, URI.join(service.proxy.fetch('endpoint'), public_base_path))
59
59
  end
@@ -15,7 +15,7 @@ module ThreeScaleToolbox
15
15
  # do not update in-place, otherwise changes will not be detected
16
16
  policies_settings = source_policies_settings.dup
17
17
 
18
- add_anonymous_access_policy(policies_settings)
18
+ reconcile_anonymous_access_policy(policies_settings)
19
19
  add_rh_sso_keycloak_role_check_policy(policies_settings)
20
20
  add_url_rewritting_policy(policies_settings)
21
21
 
@@ -31,15 +31,28 @@ module ThreeScaleToolbox
31
31
 
32
32
  private
33
33
 
34
- def add_anonymous_access_policy(policies)
35
- # only on 'open api' security req
36
- return unless api_spec.security.nil?
37
-
38
- return if policies.any? { |policy| policy['name'] == 'default_credentials' }
39
-
40
- # Anonymous policy should be before apicast policy
41
- # hence, adding as a first element
42
- policies.insert(0, anonymous_policy)
34
+ def reconcile_anonymous_access_policy(policies)
35
+ idx = policies.find_index { |p| p['name'] == 'default_credentials' }
36
+
37
+ if api_spec.security.nil?
38
+ # only on 'open api' security req
39
+ # Update anonymous policy if exists
40
+ #
41
+ if idx.nil?
42
+ # Anonymous policy should be before apicast policy
43
+ # hence, adding as a first element
44
+ policies.insert(0, anonymous_policy)
45
+ else
46
+ # only update if different
47
+ if policies[idx].dig('configuration', 'user_key') != anonymous_policy.dig(:configuration, :user_key)
48
+ policies[idx] = anonymous_policy
49
+ end
50
+ end
51
+ else
52
+ unless idx.nil?
53
+ policies.slice!(idx)
54
+ end
55
+ end
43
56
  end
44
57
 
45
58
  def anonymous_policy
@@ -108,6 +108,8 @@ module ThreeScaleToolbox
108
108
  end
109
109
 
110
110
  def openapi_parser
111
+ raise ThreeScaleToolbox::Error, 'only JSON/YAML format is supported' unless openapi_resource.is_a?(Hash)
112
+
111
113
  if openapi_resource.key?('openapi')
112
114
  ThreeScaleToolbox::OpenAPI::OAS3.build(openapi_path, openapi_resource, validate: validate)
113
115
  else
@@ -1,12 +1,3 @@
1
- require '3scale_toolbox/commands/plans_command/export/step'
2
- require '3scale_toolbox/commands/plans_command/export/read_app_plan_step'
3
- require '3scale_toolbox/commands/plans_command/export/read_plan_features_step'
4
- require '3scale_toolbox/commands/plans_command/export/read_plan_limits_step'
5
- require '3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step'
6
- require '3scale_toolbox/commands/plans_command/export/read_plan_methods_step'
7
- require '3scale_toolbox/commands/plans_command/export/read_plan_metrics_step'
8
- require '3scale_toolbox/commands/plans_command/export/write_artifacts_file_step'
9
-
10
1
  module ThreeScaleToolbox
11
2
  module Commands
12
3
  module PlansCommand
@@ -31,32 +22,64 @@ module ThreeScaleToolbox
31
22
  end
32
23
 
33
24
  def run
34
- tasks = []
35
- tasks << ReadAppPlanStep.new(context)
36
- tasks << ReadPlanLimitsStep.new(context)
37
- tasks << ReadPlanPricingRulesStep.new(context)
38
- tasks << ReadPlanFeaturesStep.new(context)
39
- tasks << ReadPlanMethods.new(context)
40
- tasks << ReadPlanMetrics.new(context)
41
- tasks << WriteArtifactsStep.new(context)
42
-
43
- # run tasks
44
- tasks.each(&:call)
25
+ select_output do |output|
26
+ plan_object = application_plan.to_hash.merge(
27
+ 'created_at' => Time.now.utc.iso8601,
28
+ 'toolbox_version' => ThreeScaleToolbox::VERSION
29
+ )
30
+ output.write(plan_object.to_yaml)
31
+ end
45
32
  end
46
33
 
47
34
  private
48
35
 
49
- def context
50
- @context ||= create_context
36
+ def remote
37
+ @remote ||= threescale_client(arguments[:remote])
38
+ end
39
+
40
+ def select_output
41
+ ios = if file
42
+ File.open(file, 'w')
43
+ else
44
+ $stdout
45
+ end
46
+ begin
47
+ yield(ios)
48
+ ensure
49
+ ios.close
50
+ end
51
+ end
52
+
53
+ def application_plan
54
+ @application_plan ||= find_application_plan
55
+ end
56
+
57
+ def find_application_plan
58
+ Entities::ApplicationPlan.find(service: product, ref: plan_system_name).tap do |p|
59
+ raise ThreeScaleToolbox::Error, "Application plan #{plan_system_name} does not exist" if p.nil?
60
+ end
61
+ end
62
+
63
+ def product
64
+ @product ||= find_product
65
+ end
66
+
67
+ def product_ref
68
+ arguments[:service_system_name]
69
+ end
70
+
71
+ def plan_system_name
72
+ arguments[:plan_system_name]
73
+ end
74
+
75
+ def find_product
76
+ Entities::Service.find(remote: remote, ref: product_ref).tap do |prd|
77
+ raise ThreeScaleToolbox::Error, "Product #{product_ref} does not exist" if prd.nil?
78
+ end
51
79
  end
52
80
 
53
- def create_context
54
- {
55
- file: options[:file],
56
- threescale_client: threescale_client(arguments[:remote]),
57
- service_system_name: arguments[:service_system_name],
58
- plan_system_name: arguments[:plan_system_name],
59
- }
81
+ def file
82
+ options[:file]
60
83
  end
61
84
  end
62
85
  end
@@ -0,0 +1,37 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module Import
5
+ class ImportBackendMetricsStep
6
+ include Step
7
+ ##
8
+ # Writes Plan metrics and methods
9
+ def call
10
+ resource_backend_metrics.each(&method(:create_metric))
11
+ resource_backend_methods.each(&method(:create_method))
12
+ end
13
+
14
+ private
15
+
16
+ def create_metric(metric_attrs)
17
+ backend = find_backend(metric_attrs.fetch('backend_system_name'))
18
+
19
+ unless backend.metrics.any? { |m| m.system_name == metric_attrs.fetch('system_name') }
20
+ Entities::BackendMetric.create(backend: backend, attrs: metric_attrs)
21
+ puts "Created backend metric: #{metric_attrs.fetch('system_name')}; backend: #{backend.system_name}"
22
+ end
23
+ end
24
+
25
+ def create_method(method_attrs)
26
+ backend = find_backend(method_attrs.fetch('backend_system_name'))
27
+
28
+ unless backend.methods.any? { |m| m.system_name == method_attrs.fetch('system_name') }
29
+ Entities::BackendMethod.create(backend: backend, attrs: method_attrs)
30
+ puts "Created backend method: #{method_attrs.fetch('system_name')}; backend: #{backend.system_name}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -2,7 +2,7 @@ module ThreeScaleToolbox
2
2
  module Commands
3
3
  module PlansCommand
4
4
  module Import
5
- class ImportMetricLimitsStep
5
+ class ImportLimitsStep
6
6
  include Step
7
7
  ##
8
8
  # Writes Plan limits
@@ -26,9 +26,18 @@ module ThreeScaleToolbox
26
26
 
27
27
  def resource_limits_processed
28
28
  resource_limits.map do |limit|
29
- metric = find_metric_by_system_name(limit.delete('metric_system_name'))
29
+ metric_system_name = limit.delete('metric_system_name')
30
+ backend_system_name = limit.delete('metric_backend_system_name')
31
+ metric_owner = if backend_system_name.nil?
32
+ service
33
+ else
34
+ find_backend(backend_system_name)
35
+ end
36
+ metric = metric_owner.find_metric_or_method(metric_system_name)
30
37
  # this ImportMetricLimitsStep step is assuming all metrics/methods have been created
31
38
  # in previous step, so finding metric should always succeed.
39
+ raise ThreeScaleToolbox::Error, "metric [#{metric_system_name}, #{backend_system_name}] not found" if metric.nil?
40
+
32
41
  limit.merge('metric_id' => metric.id)
33
42
  end
34
43
  end
@@ -14,13 +14,13 @@ module ThreeScaleToolbox
14
14
  private
15
15
 
16
16
  def missing_metrics
17
- ThreeScaleToolbox::Helper.array_difference(resource_metrics, service.metrics) do |a, b|
17
+ ThreeScaleToolbox::Helper.array_difference(resource_product_metrics, service.metrics) do |a, b|
18
18
  a['system_name'] == b.system_name
19
19
  end
20
20
  end
21
21
 
22
22
  def missing_methods
23
- ThreeScaleToolbox::Helper.array_difference(resource_methods, service.methods) do |a, b|
23
+ ThreeScaleToolbox::Helper.array_difference(resource_product_methods, service.methods) do |a, b|
24
24
  a['system_name'] == b.system_name
25
25
  end
26
26
  end
@@ -26,7 +26,18 @@ module ThreeScaleToolbox
26
26
 
27
27
  def resource_pr_processed
28
28
  resource_pricing_rules.map do |pr|
29
- metric = find_metric_by_system_name(pr.delete('metric_system_name'))
29
+ metric_system_name = pr.delete('metric_system_name')
30
+ backend_system_name = pr.delete('metric_backend_system_name')
31
+ metric_owner = if backend_system_name.nil?
32
+ service
33
+ else
34
+ find_backend(backend_system_name)
35
+ end
36
+ metric = metric_owner.find_metric_or_method(metric_system_name)
37
+ # this ImportMetricLimitsStep step is assuming all metrics/methods have been created
38
+ # in previous step, so finding metric should always succeed.
39
+ raise ThreeScaleToolbox::Error, "metric [#{metric_system_name}, #{backend_system_name}] not found" if metric.nil?
40
+
30
41
  pr.merge('metric_id' => metric.id,
31
42
  'cost_per_unit' => pr.fetch('cost_per_unit').to_f)
32
43
  end
@@ -53,6 +53,22 @@ module ThreeScaleToolbox
53
53
  artifacts_resource['methods'] || []
54
54
  end
55
55
 
56
+ def resource_product_metrics
57
+ resource_metrics.reject{ |m| m.has_key? 'backend_system_name' }
58
+ end
59
+
60
+ def resource_product_methods
61
+ resource_methods.reject{ |mth| mth.has_key? 'backend_system_name' }
62
+ end
63
+
64
+ def resource_backend_metrics
65
+ resource_metrics.select{ |m| m.has_key? 'backend_system_name' }
66
+ end
67
+
68
+ def resource_backend_methods
69
+ resource_methods.select{ |mth| mth.has_key? 'backend_system_name' }
70
+ end
71
+
56
72
  def resource_limits
57
73
  artifacts_resource['limits'] || []
58
74
  end
@@ -65,10 +81,6 @@ module ThreeScaleToolbox
65
81
  artifacts_resource['plan_features'] || []
66
82
  end
67
83
 
68
- def service_metrics_and_methods
69
- service.metrics + service.methods
70
- end
71
-
72
84
  def service_features
73
85
  context[:service_features] ||= service.features
74
86
  end
@@ -82,10 +94,6 @@ module ThreeScaleToolbox
82
94
  service_features.find { |feature| feature['system_name'] == system_name }
83
95
  end
84
96
 
85
- def find_metric_by_system_name(system_name)
86
- service_metrics_and_methods.find { |metric| metric.system_name == system_name }
87
- end
88
-
89
97
  private
90
98
 
91
99
  def find_service
@@ -100,6 +108,13 @@ module ThreeScaleToolbox
100
108
  raise ThreeScaleToolbox::Error, "Application plan #{plan_system_name} does not exist" if p.nil?
101
109
  end
102
110
  end
111
+
112
+ def find_backend(backend_system_name)
113
+ Entities::Backend.find_by_system_name(remote: threescale_client,
114
+ system_name: backend_system_name).tap do |backend|
115
+ raise ThreeScaleToolbox::Error, "Backend #{backend_system_name} does not exist" if backend.nil?
116
+ end
117
+ end
103
118
  end
104
119
  end
105
120
  end
@@ -0,0 +1,126 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module Import
5
+ class ValidatePlanStep
6
+ include Step
7
+ ##
8
+ # Creates if it does not exist, updates otherwise
9
+ def call
10
+ validate_product_metric_method_uniqueness!
11
+
12
+ validate_backend_metric_method_uniqueness!
13
+
14
+ validate_product_backend_usage_references!
15
+
16
+ validate_limit_backend_references!
17
+
18
+ validate_limit_product_references!
19
+
20
+ validate_pricingrule_backend_references!
21
+
22
+ validate_pricingrule_product_references!
23
+ end
24
+
25
+ private
26
+
27
+ def validate_product_metric_method_uniqueness!
28
+ system_name_list = (resource_product_metrics + resource_product_methods).map do |m|
29
+ m.fetch('system_name')
30
+ end
31
+ if system_name_list.length != system_name_list.uniq.length
32
+ raise ThreeScaleToolbox::Error, "Invalid content. " \
33
+ "Product metrics and method system names must be unique."
34
+ end
35
+ end
36
+
37
+ def validate_backend_metric_method_uniqueness!
38
+ metric_list = resource_backend_metrics + resource_backend_methods
39
+ backend_list = metric_list.map { |m| m.fetch('backend_system_name') }.uniq
40
+ backend_list.each do |backend_system_name|
41
+ backend_metric_list = metric_list.select do |m|
42
+ m.fetch('backend_system_name') == backend_system_name
43
+ end.map { |m| m.fetch('system_name') }
44
+
45
+ if backend_metric_list.length != backend_metric_list.uniq.length
46
+ raise ThreeScaleToolbox::Error, "Invalid content. " \
47
+ "Backend #{backend_system_name} contains metrics and method system names that are not unique"
48
+ end
49
+ end
50
+ end
51
+
52
+ def validate_product_backend_usage_references!
53
+ metric_list = resource_backend_metrics + resource_backend_methods
54
+ backend_list = metric_list.map { |m| m.fetch('backend_system_name') }.uniq
55
+ backend_usages_list = service.backend_usage_list.map(&:backend).map(&:system_name)
56
+
57
+ backend_list.each do |backend_system_name|
58
+ unless backend_usages_list.include?(backend_system_name)
59
+ raise ThreeScaleToolbox::Error, "Invalid content. " \
60
+ "Backend usage reference to backend #{backend_system_name} has not been found"
61
+ end
62
+ end
63
+ end
64
+
65
+ def validate_limit_backend_references!
66
+ metric_list = resource_backend_metrics + resource_backend_methods
67
+ limits_with_backend_ref = resource_limits.select{ |limit| limit.has_key? 'metric_backend_system_name'}
68
+ limits_with_backend_ref.each do |limit|
69
+ none = metric_list.none? do |m|
70
+ m.fetch('system_name') == limit.fetch('metric_system_name') &&
71
+ m.fetch('backend_system_name') == limit.fetch('metric_backend_system_name')
72
+ end
73
+
74
+ if none
75
+ raise ThreeScaleToolbox::Error, "Invalid content. " \
76
+ "Limit with backend metric [#{limit.fetch('metric_system_name')}, #{limit.fetch('metric_backend_system_name')}] " \
77
+ "has not been found in metric or method list"
78
+ end
79
+ end
80
+ end
81
+
82
+ def validate_limit_product_references!
83
+ metric_list = resource_product_metrics + resource_product_methods
84
+ limits = resource_limits.reject { |limit| limit.has_key? 'metric_backend_system_name'}
85
+ limits.each do |limit|
86
+ if metric_list.none? { |m| m.fetch('system_name') == limit.fetch('metric_system_name') }
87
+ raise ThreeScaleToolbox::Error, "Invalid content. " \
88
+ "Limit with product metric [#{limit.fetch('metric_system_name')}] " \
89
+ "has not been found in metric or method list"
90
+ end
91
+ end
92
+ end
93
+
94
+ def validate_pricingrule_backend_references!
95
+ metric_list = resource_backend_metrics + resource_backend_methods
96
+ pr_with_backend_ref = resource_pricing_rules.select{ |pr| pr.has_key? 'metric_backend_system_name'}
97
+ pr_with_backend_ref.each do |pr|
98
+ none = metric_list.none? do |m|
99
+ m.fetch('system_name') == pr.fetch('metric_system_name') &&
100
+ m.fetch('backend_system_name') == pr.fetch('metric_backend_system_name')
101
+ end
102
+
103
+ if none
104
+ raise ThreeScaleToolbox::Error, "Invalid content. " \
105
+ "PricingRule with backend metric [#{pr.fetch('metric_system_name')}, #{pr.fetch('metric_backend_system_name')}] " \
106
+ "has not been found in metric or method list"
107
+ end
108
+ end
109
+ end
110
+
111
+ def validate_pricingrule_product_references!
112
+ metric_list = resource_product_metrics + resource_product_methods
113
+ prs = resource_pricing_rules.reject { |pr| pr.has_key? 'metric_backend_system_name'}
114
+ prs.each do |pr|
115
+ if metric_list.none? { |m| m.fetch('system_name') == pr.fetch('metric_system_name') }
116
+ raise ThreeScaleToolbox::Error, "Invalid content. " \
117
+ "PricingRule with product metric [#{pr.fetch('metric_system_name')}] " \
118
+ "has not been found in metric or method list"
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -1,9 +1,11 @@
1
1
  require '3scale_toolbox/commands/plans_command/import/step'
2
+ require '3scale_toolbox/commands/plans_command/import/validate_plan_step'
2
3
  require '3scale_toolbox/commands/plans_command/import/create_or_update_app_plan_step'
3
4
  require '3scale_toolbox/commands/plans_command/import/import_plan_features_step'
4
5
  require '3scale_toolbox/commands/plans_command/import/import_plan_metrics_step'
5
6
  require '3scale_toolbox/commands/plans_command/import/import_plan_limits_step'
6
7
  require '3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step'
8
+ require '3scale_toolbox/commands/plans_command/import/import_backend_metrics_step'
7
9
 
8
10
  module ThreeScaleToolbox
9
11
  module Commands
@@ -31,9 +33,11 @@ module ThreeScaleToolbox
31
33
 
32
34
  def run
33
35
  tasks = []
36
+ tasks << ValidatePlanStep.new(context)
34
37
  tasks << CreateOrUpdateAppPlanStep.new(context)
35
38
  tasks << ImportMetricsStep.new(context)
36
- tasks << ImportMetricLimitsStep.new(context)
39
+ tasks << ImportBackendMetricsStep.new(context)
40
+ tasks << ImportLimitsStep.new(context)
37
41
  tasks << ImportPricingRulesStep.new(context)
38
42
  tasks << ImportPlanFeaturesStep.new(context)
39
43
 
@@ -27,6 +27,7 @@ module ThreeScaleToolbox
27
27
  # First metrics as methods need 'hits' metric in target backend
28
28
  tasks << Commands::BackendCommand::CopyCommand::CopyMetricsTask.new(backend_context)
29
29
  tasks << Commands::BackendCommand::CopyCommand::CopyMethodsTask.new(backend_context)
30
+ tasks << Commands::BackendCommand::CopyCommand::DeleteMappingRulesTask.new(backend_context)
30
31
  tasks << Commands::BackendCommand::CopyCommand::CopyMappingRulesTask.new(backend_context)
31
32
  tasks.each(&:call)
32
33
 
@@ -72,12 +73,17 @@ module ThreeScaleToolbox
72
73
  context.fetch(:logger)
73
74
  end
74
75
 
76
+ def delete_mapping_rules
77
+ context.fetch(:delete_mapping_rules, false)
78
+ end
79
+
75
80
  def create_backend_context(source_backend)
76
81
  {
77
82
  source_remote: source_remote,
78
83
  target_remote: target_remote,
79
84
  source_backend: source_backend,
80
85
  source_backend_ref: source_backend.id,
86
+ delete_mapping_rules: delete_mapping_rules,
81
87
  logger: logger
82
88
  }
83
89
  end