3scale_toolbox 0.18.3 → 0.19.3

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