3scale_toolbox 0.15.0 → 0.18.2

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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/3scale_toolbox.gemspec +2 -2
  3. data/README.md +15 -9
  4. data/lib/3scale_toolbox.rb +3 -1
  5. data/lib/3scale_toolbox/3scale_client_factory.rb +3 -4
  6. data/lib/3scale_toolbox/cli.rb +4 -0
  7. data/lib/3scale_toolbox/cli/custom_table_printer.rb +32 -0
  8. data/lib/3scale_toolbox/cli/error_handler.rb +17 -14
  9. data/lib/3scale_toolbox/cli/json_printer.rb +13 -0
  10. data/lib/3scale_toolbox/cli/output_flag.rb +20 -0
  11. data/lib/3scale_toolbox/cli/yaml_printer.rb +13 -0
  12. data/lib/3scale_toolbox/commands.rb +7 -1
  13. data/lib/3scale_toolbox/commands/activedocs_command/apply_command.rb +33 -10
  14. data/lib/3scale_toolbox/commands/activedocs_command/create_command.rb +22 -7
  15. data/lib/3scale_toolbox/commands/activedocs_command/list_command.rb +10 -17
  16. data/lib/3scale_toolbox/commands/application_command/apply_command.rb +27 -4
  17. data/lib/3scale_toolbox/commands/application_command/create_command.rb +16 -1
  18. data/lib/3scale_toolbox/commands/application_command/list_command.rb +10 -13
  19. data/lib/3scale_toolbox/commands/application_command/show_command.rb +8 -14
  20. data/lib/3scale_toolbox/commands/backend_command.rb +22 -0
  21. data/lib/3scale_toolbox/commands/backend_command/copy_command.rb +65 -0
  22. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_mapping_rules_task.rb +36 -0
  23. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_methods_task.rb +35 -0
  24. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_metrics_task.rb +30 -0
  25. data/lib/3scale_toolbox/commands/backend_command/copy_command/create_or_update_target_backend_task.rb +46 -0
  26. data/lib/3scale_toolbox/commands/backend_command/copy_command/task.rb +67 -0
  27. data/lib/3scale_toolbox/commands/copy_command.rb +2 -2
  28. data/lib/3scale_toolbox/commands/copy_command/service_command.rb +40 -0
  29. data/lib/3scale_toolbox/commands/import_command/issuer_type_transformer.rb +16 -0
  30. data/lib/3scale_toolbox/commands/import_command/openapi.rb +6 -2
  31. data/lib/3scale_toolbox/commands/import_command/openapi/create_mapping_rule_step.rb +2 -1
  32. data/lib/3scale_toolbox/commands/import_command/openapi/create_method_step.rb +5 -14
  33. data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +4 -0
  34. data/lib/3scale_toolbox/commands/import_command/openapi/update_service_proxy_step.rb +1 -0
  35. data/lib/3scale_toolbox/commands/methods_command/apply_command.rb +28 -8
  36. data/lib/3scale_toolbox/commands/methods_command/create_command.rb +23 -3
  37. data/lib/3scale_toolbox/commands/methods_command/delete_command.rb +1 -1
  38. data/lib/3scale_toolbox/commands/methods_command/list_command.rb +7 -13
  39. data/lib/3scale_toolbox/commands/metrics_command/apply_command.rb +26 -4
  40. data/lib/3scale_toolbox/commands/metrics_command/create_command.rb +23 -1
  41. data/lib/3scale_toolbox/commands/metrics_command/list_command.rb +7 -12
  42. data/lib/3scale_toolbox/commands/plans_command/apply_command.rb +36 -7
  43. data/lib/3scale_toolbox/commands/plans_command/create_command.rb +23 -1
  44. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_limits_step.rb +1 -1
  45. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_methods_step.rb +2 -2
  46. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_metrics_step.rb +2 -2
  47. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step.rb +1 -2
  48. data/lib/3scale_toolbox/commands/plans_command/export/step.rb +8 -20
  49. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_limits_step.rb +12 -14
  50. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_metrics_step.rb +6 -13
  51. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +12 -20
  52. data/lib/3scale_toolbox/commands/plans_command/import/step.rb +2 -22
  53. data/lib/3scale_toolbox/commands/plans_command/list_command.rb +8 -13
  54. data/lib/3scale_toolbox/commands/plans_command/show_command.rb +7 -15
  55. data/lib/3scale_toolbox/commands/policies_command.rb +24 -0
  56. data/lib/3scale_toolbox/commands/policies_command/export_command.rb +98 -0
  57. data/lib/3scale_toolbox/commands/policies_command/import_command.rb +61 -0
  58. data/lib/3scale_toolbox/commands/product_command.rb +26 -0
  59. data/lib/3scale_toolbox/commands/product_command/copy_command.rb +82 -0
  60. data/lib/3scale_toolbox/commands/product_command/copy_command/copy_backends_task.rb +88 -0
  61. data/lib/3scale_toolbox/commands/product_command/copy_command/delete_target_backend_usages_task.rb +48 -0
  62. data/lib/3scale_toolbox/commands/product_command/export_command.rb +81 -0
  63. data/lib/3scale_toolbox/commands/product_command/import_command.rb +125 -0
  64. data/lib/3scale_toolbox/commands/proxy_config_command.rb +5 -0
  65. data/lib/3scale_toolbox/commands/proxy_config_command/deploy_command.rb +54 -0
  66. data/lib/3scale_toolbox/commands/proxy_config_command/export_command.rb +74 -0
  67. data/lib/3scale_toolbox/commands/proxy_config_command/helper.rb +15 -0
  68. data/lib/3scale_toolbox/commands/proxy_config_command/list_command.rb +13 -29
  69. data/lib/3scale_toolbox/commands/proxy_config_command/show_command.rb +20 -23
  70. data/lib/3scale_toolbox/commands/service_command.rb +7 -5
  71. data/lib/3scale_toolbox/commands/service_command/apply_command.rb +69 -58
  72. data/lib/3scale_toolbox/commands/service_command/copy_command.rb +95 -0
  73. data/lib/3scale_toolbox/commands/service_command/copy_command/bump_proxy_version_task.rb +36 -0
  74. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_activedocs_task.rb +49 -0
  75. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_app_plans_task.rb +35 -0
  76. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_limits_task.rb +38 -0
  77. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_mapping_rules_task.rb +35 -0
  78. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_methods_task.rb +37 -0
  79. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_metrics_task.rb +37 -0
  80. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_policies_task.rb +17 -0
  81. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_pricingrules_task.rb +41 -0
  82. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_service_proxy_task.rb +32 -0
  83. data/lib/3scale_toolbox/commands/service_command/copy_command/create_or_update_service_task.rb +49 -0
  84. data/lib/3scale_toolbox/commands/service_command/copy_command/destroy_mapping_rules_task.rb +38 -0
  85. data/lib/3scale_toolbox/commands/service_command/copy_command/task.rb +85 -0
  86. data/lib/3scale_toolbox/commands/service_command/create_command.rb +58 -44
  87. data/lib/3scale_toolbox/commands/service_command/delete_command.rb +31 -33
  88. data/lib/3scale_toolbox/commands/service_command/list_command.rb +24 -34
  89. data/lib/3scale_toolbox/commands/service_command/show_command.rb +39 -44
  90. data/lib/3scale_toolbox/commands/update_command.rb +3 -3
  91. data/lib/3scale_toolbox/commands/update_command/{update_service.rb → service_command.rb} +22 -18
  92. data/lib/3scale_toolbox/commands/update_command/service_command/copy_service_settings_task.rb +35 -0
  93. data/lib/3scale_toolbox/commands/update_command/service_command/delete_activedocs_task.rb +24 -0
  94. data/lib/3scale_toolbox/crds.rb +16 -0
  95. data/lib/3scale_toolbox/crds/application_plan_dump.rb +19 -0
  96. data/lib/3scale_toolbox/crds/backend_dump.rb +39 -0
  97. data/lib/3scale_toolbox/crds/backend_mapping_rule_dump.rb +26 -0
  98. data/lib/3scale_toolbox/crds/backend_method_dump.rb +12 -0
  99. data/lib/3scale_toolbox/crds/backend_metric_dump.rb +13 -0
  100. data/lib/3scale_toolbox/crds/backend_parser.rb +55 -0
  101. data/lib/3scale_toolbox/crds/backend_usage_dump.rb +11 -0
  102. data/lib/3scale_toolbox/crds/limit_dump.rb +37 -0
  103. data/lib/3scale_toolbox/crds/mapping_rule_dump.rb +26 -0
  104. data/lib/3scale_toolbox/crds/method_dump.rb +12 -0
  105. data/lib/3scale_toolbox/crds/metric_dump.rb +13 -0
  106. data/lib/3scale_toolbox/crds/pricing_rule_dump.rb +38 -0
  107. data/lib/3scale_toolbox/crds/product_deployment_parser.rb +329 -0
  108. data/lib/3scale_toolbox/crds/product_dump.rb +157 -0
  109. data/lib/3scale_toolbox/crds/product_parser.rb +114 -0
  110. data/lib/3scale_toolbox/crds/remote.rb +682 -0
  111. data/lib/3scale_toolbox/entities.rb +8 -0
  112. data/lib/3scale_toolbox/entities/activedocs.rb +12 -0
  113. data/lib/3scale_toolbox/entities/application_plan.rb +74 -39
  114. data/lib/3scale_toolbox/entities/backend.rb +187 -0
  115. data/lib/3scale_toolbox/entities/backend_mapping_rule.rb +102 -0
  116. data/lib/3scale_toolbox/entities/backend_method.rb +99 -0
  117. data/lib/3scale_toolbox/entities/backend_metric.rb +98 -0
  118. data/lib/3scale_toolbox/entities/backend_usage.rb +105 -0
  119. data/lib/3scale_toolbox/entities/limit.rb +71 -0
  120. data/lib/3scale_toolbox/entities/mapping_rule.rb +90 -0
  121. data/lib/3scale_toolbox/entities/method.rb +33 -19
  122. data/lib/3scale_toolbox/entities/metric.rb +29 -18
  123. data/lib/3scale_toolbox/entities/pricing_rule.rb +63 -0
  124. data/lib/3scale_toolbox/entities/proxy_config.rb +0 -1
  125. data/lib/3scale_toolbox/entities/service.rb +166 -48
  126. data/lib/3scale_toolbox/error.rb +53 -0
  127. data/lib/3scale_toolbox/helper.rb +17 -0
  128. data/lib/3scale_toolbox/openapi/oas3.rb +1 -1
  129. data/lib/3scale_toolbox/proxy_logger.rb +5 -1
  130. data/lib/3scale_toolbox/remote_cache.rb +157 -0
  131. data/lib/3scale_toolbox/remotes.rb +2 -2
  132. data/lib/3scale_toolbox/version.rb +1 -1
  133. data/licenses.xml +113 -45
  134. metadata +75 -26
  135. data/lib/3scale_toolbox/commands/copy_command/copy_service.rb +0 -144
  136. data/lib/3scale_toolbox/tasks.rb +0 -15
  137. data/lib/3scale_toolbox/tasks/bump_proxy_version_task.rb +0 -32
  138. data/lib/3scale_toolbox/tasks/copy_activedocs_task.rb +0 -42
  139. data/lib/3scale_toolbox/tasks/copy_app_plans_task.rb +0 -31
  140. data/lib/3scale_toolbox/tasks/copy_limits_task.rb +0 -36
  141. data/lib/3scale_toolbox/tasks/copy_mapping_rules_task.rb +0 -32
  142. data/lib/3scale_toolbox/tasks/copy_methods_task.rb +0 -36
  143. data/lib/3scale_toolbox/tasks/copy_metrics_task.rb +0 -33
  144. data/lib/3scale_toolbox/tasks/copy_policies_task.rb +0 -13
  145. data/lib/3scale_toolbox/tasks/copy_pricingrules_task.rb +0 -41
  146. data/lib/3scale_toolbox/tasks/copy_service_proxy_task.rb +0 -13
  147. data/lib/3scale_toolbox/tasks/copy_service_settings_task.rb +0 -38
  148. data/lib/3scale_toolbox/tasks/copy_task.rb +0 -66
  149. data/lib/3scale_toolbox/tasks/delete_activedocs_task.rb +0 -22
  150. data/lib/3scale_toolbox/tasks/destroy_mapping_rules_task.rb +0 -22
  151. data/lib/3scale_toolbox/tasks/helper_task.rb +0 -25
@@ -0,0 +1,95 @@
1
+ require '3scale_toolbox/commands/service_command/copy_command/task'
2
+ require '3scale_toolbox/commands/service_command/copy_command/create_or_update_service_task'
3
+ require '3scale_toolbox/commands/service_command/copy_command/copy_limits_task'
4
+ require '3scale_toolbox/commands/service_command/copy_command/copy_mapping_rules_task'
5
+ require '3scale_toolbox/commands/service_command/copy_command/copy_activedocs_task'
6
+ require '3scale_toolbox/commands/service_command/copy_command/copy_app_plans_task'
7
+ require '3scale_toolbox/commands/service_command/copy_command/copy_methods_task'
8
+ require '3scale_toolbox/commands/service_command/copy_command/copy_metrics_task'
9
+ require '3scale_toolbox/commands/service_command/copy_command/copy_policies_task'
10
+ require '3scale_toolbox/commands/service_command/copy_command/copy_pricingrules_task'
11
+ require '3scale_toolbox/commands/service_command/copy_command/copy_service_proxy_task'
12
+ require '3scale_toolbox/commands/service_command/copy_command/destroy_mapping_rules_task'
13
+ require '3scale_toolbox/commands/service_command/copy_command/bump_proxy_version_task'
14
+
15
+ module ThreeScaleToolbox
16
+ module Commands
17
+ module ServiceCommand
18
+ class CopySubcommand < Cri::CommandRunner
19
+ include ThreeScaleToolbox::Command
20
+
21
+ def self.command
22
+ Cri::Command.define do
23
+ name 'copy'
24
+ usage 'copy [opts] -s <src> -d <dst> <source-service>'
25
+ summary 'Copy service'
26
+ description <<-HEREDOC
27
+ This command makes a copy of the referenced service.
28
+ Target service will be searched by source service system name. System name can be overriden with `--target_system_name` option.
29
+ If a service with the selected `system_name` is not found, it will be created.
30
+ \n Components of the service being copied:
31
+ \nservice settings
32
+ \nproxy settings
33
+ \npricing rules
34
+ \nactivedocs
35
+ \nmetrics
36
+ \nmethods
37
+ \napplication plans
38
+ \nmapping rules
39
+ HEREDOC
40
+
41
+ option :s, :source, '3scale source instance. Url or remote name', argument: :required
42
+ option :d, :destination, '3scale target instance. Url or remote name', argument: :required
43
+ option :t, 'target_system_name', 'Target system name. Default to source system name', argument: :required
44
+ flag :f, :force, 'Overwrites the mapping rules by deleting all rules from target service first'
45
+ flag :r, 'rules-only', 'Only mapping rules are copied'
46
+ param :source_service
47
+
48
+ runner CopySubcommand
49
+ end
50
+ end
51
+
52
+ def run
53
+ tasks = []
54
+ unless option_rules_only
55
+ tasks << CopyCommand::CreateOrUpdateTargetServiceTask.new(context)
56
+ tasks << CopyCommand::CopyServiceProxyTask.new(context)
57
+ tasks << CopyCommand::CopyMethodsTask.new(context)
58
+ tasks << CopyCommand::CopyMetricsTask.new(context)
59
+ tasks << CopyCommand::CopyApplicationPlansTask.new(context)
60
+ tasks << CopyCommand::CopyLimitsTask.new(context)
61
+ tasks << CopyCommand::CopyPoliciesTask.new(context)
62
+ tasks << CopyCommand::CopyPricingRulesTask.new(context)
63
+ tasks << CopyCommand::CopyActiveDocsTask.new(context)
64
+ end
65
+ tasks << CopyCommand::DestroyMappingRulesTask.new(context)
66
+ tasks << CopyCommand::CopyMappingRulesTask.new(context)
67
+ tasks.each(&:call)
68
+
69
+ # This should be the last step
70
+ CopyCommand::BumpProxyVersionTask.new(service: context[:target]).call
71
+ end
72
+
73
+ private
74
+
75
+ def context
76
+ @context ||= create_context
77
+ end
78
+
79
+ def create_context
80
+ {
81
+ source_remote: threescale_client(fetch_required_option(:source)),
82
+ target_remote: threescale_client(fetch_required_option(:destination)),
83
+ source_service_ref: arguments[:source_service],
84
+ option_target_system_name: options[:target_system_name],
85
+ delete_mapping_rules: options[:force]
86
+ }
87
+ end
88
+
89
+ def option_rules_only
90
+ options[:'rules-only']
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,36 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class BumpProxyVersionTask
6
+ attr_reader :service
7
+
8
+ def initialize(service:)
9
+ @service = service
10
+ end
11
+
12
+ ##
13
+ # bumps proxy config version to propagate proxy settings updates
14
+ def call
15
+ # Proxy update is the mechanism to increase version of the proxy,
16
+ # Hence propagating (mapping rules, poicies, oidc, auth) update to
17
+ # latest proxy config, making available to gateway.
18
+
19
+ # Currently it is done always because mapping rules, at least, are always created
20
+ # So they need to be propagated
21
+ proxy_settings = {
22
+ # Adding harmless attribute to avoid empty body
23
+ # update_proxy cannot be done with empty body
24
+ # and must be done to increase proxy version
25
+ # If proxy settings have not been changed since last update,
26
+ # this request will not have effect and proxy config version will not be bumped.
27
+ service_id: service.id
28
+ }
29
+
30
+ service.update_proxy proxy_settings
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,49 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyActiveDocsTask
6
+ include Task
7
+
8
+ def call
9
+ logger.info 'copying all service ActiveDocs'
10
+
11
+ source.activedocs.each(&method(:apply_target_activedoc))
12
+ end
13
+
14
+ private
15
+
16
+ def apply_target_activedoc(source_activedoc)
17
+ activedocs = Entities::ActiveDocs.find_by_system_name(remote: target.remote,
18
+ system_name: source_activedoc.system_name)
19
+ if activedocs.nil?
20
+ activedocs = Entities::ActiveDocs.create(remote: target.remote, attrs: create_attrs(source_activedoc))
21
+ activedocs_report[activedocs.system_name] = { 'id' => activedocs.id, 'status' => 'created' }
22
+ elsif activedocs.attrs.fetch('service_id') == target.id
23
+ activedocs.update(update_attrs(source_activedoc))
24
+ activedocs_report[activedocs.system_name] = { 'id' => activedocs.id, 'status' => 'updated' }
25
+ else
26
+ # activedocs with same system_name exists, but now owned by target service
27
+ new_attrs = create_attrs(source_activedoc)
28
+ new_attrs['system_name'] = "#{source_activedoc.system_name}#{target.id}"
29
+ activedocs = Entities::ActiveDocs.create(remote: target.remote, attrs: new_attrs)
30
+ activedocs_report[activedocs.system_name] = { 'id' => activedocs.id, 'status' => 'created' }
31
+ end
32
+ end
33
+
34
+ def update_attrs(activedoc)
35
+ create_attrs(activedoc)
36
+ end
37
+
38
+ def create_attrs(activedoc)
39
+ # keep same system_name
40
+ new_attrs = activedoc.attrs.reject { |key, _| %w[id created_at updated_at].include? key }
41
+ new_attrs.tap do |attrs|
42
+ attrs['service_id'] = target.id
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,35 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyApplicationPlansTask
6
+ include Task
7
+
8
+ def call
9
+ missing_regular_plans.each do |plan|
10
+ plan_attrs = plan.attrs.clone
11
+ plan_attrs.delete('links')
12
+ plan_attrs.delete('default') # TODO: handle default plan
13
+ ThreeScaleToolbox::Entities::ApplicationPlan.create(service: target, plan_attrs: plan_attrs)
14
+ end
15
+
16
+ logger.info "target service missing #{missing_regular_plans.size} application plans"
17
+ report['missing_application_plans_created'] = missing_regular_plans.size
18
+ end
19
+
20
+ private
21
+
22
+ def missing_regular_plans
23
+ missing_plans.reject(&:custom)
24
+ end
25
+
26
+ def missing_plans
27
+ @missing_plans ||= ThreeScaleToolbox::Helper.array_difference(source.plans, target.plans) do |src, target|
28
+ src.system_name == target.system_name
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyLimitsTask
6
+ include Task
7
+
8
+ def call
9
+ plan_mapping = Helper.application_plan_mapping(source.plans, target.plans)
10
+ plan_mapping.each do |source_plan, target_plan|
11
+ missing_limits = compute_missing_limits(source_plan.limits, target_plan.limits)
12
+ missing_limits.each do |limit|
13
+ target_plan.create_limit(metrics_map.fetch(limit.metric_id), limit.attrs)
14
+ end
15
+ logger.info "Missing #{missing_limits.size} plan limits from target application plan " \
16
+ "#{target_plan.id}. Source plan #{source_plan.id}"
17
+
18
+ plans_report[target_plan.system_name] = {'application_plan_id' => target_plan.id} unless plans_report.has_key? target_plan.system_name
19
+ plans_report[target_plan.system_name].merge!({'missing_limits_created' => missing_limits.size})
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def metrics_map
26
+ @metrics_map ||= source.metrics_mapping(target)
27
+ end
28
+
29
+ def compute_missing_limits(source_limits, target_limits)
30
+ ThreeScaleToolbox::Helper.array_difference(source_limits, target_limits) do |limit, target_limit|
31
+ limit.period == target_limit.period && metrics_map.fetch(limit.metric_id) == target_limit.metric_id
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyMappingRulesTask
6
+ include Task
7
+
8
+ def call
9
+ missing_rules.each do |mapping_rule|
10
+ mr_attrs = mapping_rule.attrs.merge('metric_id' => metrics_map.fetch(mapping_rule.metric_id))
11
+ Entities::MappingRule.create(service: target, attrs: mr_attrs)
12
+ end
13
+ logger.info "created #{missing_rules.size} mapping rules"
14
+ report['missing_mapping_rules_created'] = missing_rules.size
15
+ end
16
+
17
+ private
18
+
19
+ def metrics_map
20
+ @metrics_map ||= source.metrics_mapping(target)
21
+ end
22
+
23
+ def missing_rules
24
+ @missing_rules ||= ThreeScaleToolbox::Helper.array_difference(source.mapping_rules, target.mapping_rules) do |source_rule, target_rule|
25
+ source_rule.pattern == target_rule.pattern &&
26
+ source_rule.http_method == target_rule.http_method &&
27
+ source_rule.delta == target_rule.delta &&
28
+ metrics_map.fetch(source_rule.metric_id) == target_rule.metric_id
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyMethodsTask
6
+ include Task
7
+
8
+ def call
9
+ logger.info "original service hits metric #{source.hits.id} has #{source.methods.size} methods"
10
+ logger.info "target service hits metric #{target.hits.id} has #{target.methods.size} methods"
11
+ missing_methods.each(&method(:create_method))
12
+ logger.info "created #{missing_methods.size} missing methods on target service"
13
+ report['missing_methods_created'] = missing_methods.size
14
+ end
15
+
16
+ private
17
+
18
+ def create_method(method)
19
+ new_method = method.attrs.reject { |key, _| %w[id links].include? key }
20
+ Entities::Method.create(service: target, attrs: new_method)
21
+ rescue ThreeScaleToolbox::ThreeScaleApiError => e
22
+ raise e unless ThreeScaleToolbox::Helper.system_name_already_taken_error?(e.apierrors)
23
+
24
+ warn "[WARN] method #{method.system_name} not created. " \
25
+ 'Metric with the same system_name exists.'
26
+ end
27
+
28
+ def missing_methods
29
+ @missing_methods ||= ThreeScaleToolbox::Helper.array_difference(source.methods, target.methods) do |method, target|
30
+ method.system_name == target.system_name
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyMetricsTask
6
+ include Task
7
+
8
+ def call
9
+ logger.info "original service has #{source.metrics.size} metrics"
10
+ logger.info "target service has #{target.metrics.size} metrics"
11
+ missing_metrics.each(&method(:create_metric))
12
+ logger.info "created #{missing_metrics.size} metrics on the target service"
13
+ report['missing_metrics_created'] = missing_metrics.size
14
+ end
15
+
16
+ private
17
+
18
+ def create_metric(metric)
19
+ new_metric = metric.attrs.reject { |key, _| %w[id links].include? key }
20
+ Entities::Metric.create(service: target, attrs: new_metric)
21
+ rescue ThreeScaleToolbox::ThreeScaleApiError => e
22
+ raise e unless ThreeScaleToolbox::Helper.system_name_already_taken_error?(e.apierrors)
23
+
24
+ warn "[WARN] metric #{metric.system_name} not created. " \
25
+ 'Method with the same system_name exists.'
26
+ end
27
+
28
+ def missing_metrics
29
+ @missing_metrics ||= ThreeScaleToolbox::Helper.array_difference(source.metrics, target.metrics) do |s_m, t_m|
30
+ s_m.system_name == t_m.system_name
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyPoliciesTask
6
+ include Task
7
+
8
+ def call
9
+ logger.info 'copy proxy policies'
10
+ source_policies = source.policies
11
+ target.update_policies('policies_config' => source_policies)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,41 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyPricingRulesTask
6
+ include Task
7
+
8
+ def call
9
+ plan_mapping = Helper.application_plan_mapping(source.plans, target.plans)
10
+ plan_mapping.each do |source_plan, target_plan|
11
+ missing_pricing_rules = compute_missing_pricing_rules(source_plan.pricing_rules, target_plan.pricing_rules)
12
+ missing_pricing_rules.each do |pricing_rule|
13
+ target_plan.create_pricing_rule(metrics_map.fetch(pricing_rule.metric_id), pricing_rule.attrs)
14
+ end
15
+ logger.info "Missing #{missing_pricing_rules.size} pricing rules from target application plan " \
16
+ "#{target_plan.id}. Source plan #{source_plan.id}"
17
+
18
+ plans_report[target_plan.system_name] = {'application_plan_id' => target_plan.id} unless plans_report.has_key? target_plan.system_name
19
+ plans_report[target_plan.system_name].merge!({'missing_pricing_rules_created' => missing_pricing_rules.size})
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def metrics_map
26
+ @metrics_map ||= source.metrics_mapping(target)
27
+ end
28
+
29
+ def compute_missing_pricing_rules(source_pricing_rules, target_pricing_rules)
30
+ ThreeScaleToolbox::Helper.array_difference(source_pricing_rules, target_pricing_rules) do |src, target_pr|
31
+ src.cost_per_unit == target_pr.cost_per_unit &&
32
+ src.min == target_pr.min &&
33
+ src.max == target_pr.max &&
34
+ metrics_map.fetch(src.metric_id) == target_pr.metric_id
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CopyServiceProxyTask
6
+ include Task
7
+
8
+ def call
9
+ target.update_proxy target_proxy_attrs
10
+ target.update_oidc source.oidc if source.attrs['backend_version'] == 'oidc'
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
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end