3scale_toolbox 0.5.1 → 0.6.0

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +143 -23
  3. data/exe/3scale +10 -3
  4. data/lib/3scale_toolbox.rb +18 -0
  5. data/lib/3scale_toolbox/3scale_client_factory.rb +33 -0
  6. data/lib/3scale_toolbox/base_command.rb +52 -14
  7. data/lib/3scale_toolbox/cli.rb +26 -5
  8. data/lib/3scale_toolbox/cli/error_handler.rb +120 -0
  9. data/lib/3scale_toolbox/commands.rb +3 -9
  10. data/lib/3scale_toolbox/commands/3scale_command.rb +8 -6
  11. data/lib/3scale_toolbox/commands/copy_command.rb +4 -4
  12. data/lib/3scale_toolbox/commands/copy_command/copy_service.rb +40 -193
  13. data/lib/3scale_toolbox/commands/help_command.rb +1 -1
  14. data/lib/3scale_toolbox/commands/import_command.rb +6 -4
  15. data/lib/3scale_toolbox/commands/import_command/import_csv.rb +15 -41
  16. data/lib/3scale_toolbox/commands/import_command/openapi.rb +70 -0
  17. data/lib/3scale_toolbox/commands/import_command/openapi/create_mapping_rule_step.rb +18 -0
  18. data/lib/3scale_toolbox/commands/import_command/openapi/create_method_step.rb +39 -0
  19. data/lib/3scale_toolbox/commands/import_command/openapi/create_service_step.rb +69 -0
  20. data/lib/3scale_toolbox/commands/import_command/openapi/mapping_rule.rb +35 -0
  21. data/lib/3scale_toolbox/commands/import_command/openapi/method.rb +25 -0
  22. data/lib/3scale_toolbox/commands/import_command/openapi/operation.rb +22 -0
  23. data/lib/3scale_toolbox/commands/import_command/openapi/resource_reader.rb +49 -0
  24. data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +45 -0
  25. data/lib/3scale_toolbox/commands/import_command/openapi/threescale_api_spec.rb +33 -0
  26. data/lib/3scale_toolbox/commands/remote_command.rb +36 -0
  27. data/lib/3scale_toolbox/commands/remote_command/remote_add.rb +47 -0
  28. data/lib/3scale_toolbox/commands/remote_command/remote_list.rb +29 -0
  29. data/lib/3scale_toolbox/commands/remote_command/remote_remove.rb +26 -0
  30. data/lib/3scale_toolbox/commands/remote_command/remote_rename.rb +42 -0
  31. data/lib/3scale_toolbox/commands/update_command.rb +4 -4
  32. data/lib/3scale_toolbox/commands/update_command/update_service.rb +45 -235
  33. data/lib/3scale_toolbox/configuration.rb +35 -0
  34. data/lib/3scale_toolbox/entities.rb +1 -0
  35. data/lib/3scale_toolbox/entities/service.rb +113 -0
  36. data/lib/3scale_toolbox/error.rb +8 -0
  37. data/lib/3scale_toolbox/helper.rb +37 -0
  38. data/lib/3scale_toolbox/remotes.rb +93 -0
  39. data/lib/3scale_toolbox/tasks.rb +10 -0
  40. data/lib/3scale_toolbox/tasks/copy_app_plans_task.rb +31 -0
  41. data/lib/3scale_toolbox/tasks/copy_limits_task.rb +36 -0
  42. data/lib/3scale_toolbox/tasks/copy_mapping_rules_task.rb +29 -0
  43. data/lib/3scale_toolbox/tasks/copy_methods_task.rb +29 -0
  44. data/lib/3scale_toolbox/tasks/copy_metrics_task.rb +33 -0
  45. data/lib/3scale_toolbox/tasks/copy_service_proxy_task.rb +12 -0
  46. data/lib/3scale_toolbox/tasks/copy_task.rb +26 -0
  47. data/lib/3scale_toolbox/tasks/destroy_mapping_rules_task.rb +22 -0
  48. data/lib/3scale_toolbox/tasks/helper_task.rb +25 -0
  49. data/lib/3scale_toolbox/tasks/update_service_settings_task.rb +32 -0
  50. data/lib/3scale_toolbox/version.rb +1 -1
  51. metadata +87 -11
@@ -0,0 +1,45 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ImportCommand
4
+ module OpenAPI
5
+ module Step
6
+ attr_reader :context
7
+
8
+ def initialize(context)
9
+ @context = context
10
+ end
11
+
12
+ # Can be nil on initialization time and not nil afterwards
13
+ # method to fetch from context required
14
+ def service
15
+ context[:target]
16
+ end
17
+
18
+ def service=(service)
19
+ context[:target] = service
20
+ end
21
+
22
+ def api_spec
23
+ context[:api_spec]
24
+ end
25
+
26
+ def threescale_client
27
+ context[:threescale_client]
28
+ end
29
+
30
+ def operations
31
+ # api_spec.operations are readonly
32
+ # store operations in context
33
+ # each operation can be extended with extra information to be used later
34
+ context[:operations] ||= api_spec.operations
35
+ end
36
+
37
+ def target_system_name
38
+ # could be nil
39
+ context[:target_system_name]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,33 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ImportCommand
4
+ module OpenAPI
5
+ class ThreeScaleApiSpec
6
+ attr_reader :openapi
7
+
8
+ def initialize(openapi)
9
+ @openapi = openapi
10
+ end
11
+
12
+ def title
13
+ openapi.info.title
14
+ end
15
+
16
+ def description
17
+ openapi.info.description
18
+ end
19
+
20
+ def operations
21
+ openapi.operations.map do |op|
22
+ Operation.new(
23
+ path: "#{openapi.base_path}#{op.path}",
24
+ verb: op.verb,
25
+ operationId: op.operationId
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,36 @@
1
+ require 'cri'
2
+ require '3scale_toolbox/base_command'
3
+ require '3scale_toolbox/remotes'
4
+ require '3scale_toolbox/commands/remote_command/remote_add'
5
+ require '3scale_toolbox/commands/remote_command/remote_remove'
6
+ require '3scale_toolbox/commands/remote_command/remote_rename'
7
+ require '3scale_toolbox/commands/remote_command/remote_list'
8
+
9
+ module ThreeScaleToolbox
10
+ module Commands
11
+ module RemoteCommand
12
+ class RemoteCommand < Cri::CommandRunner
13
+ include ThreeScaleToolbox::Command
14
+
15
+ def self.command
16
+ Cri::Command.define do
17
+ name 'remote'
18
+ usage 'remote <sub-command> [options]'
19
+ summary 'remotes super command'
20
+ description 'Manage your remotes'
21
+ runner RemoteCommand
22
+ end
23
+ end
24
+
25
+ def run
26
+ puts command.help
27
+ end
28
+
29
+ add_subcommand(RemoteAddSubcommand)
30
+ add_subcommand(RemoteRemoveSubcommand)
31
+ add_subcommand(RemoteRenameSubcommand)
32
+ add_subcommand(RemoteListSubcommand)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,47 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module RemoteCommand
4
+ class RemoteAddSubcommand < Cri::CommandRunner
5
+ include ThreeScaleToolbox::Command
6
+
7
+ def self.command
8
+ Cri::Command.define do
9
+ name 'add'
10
+ usage 'add <name> <url>'
11
+ summary 'remote add'
12
+ description 'Add new remote to the list'
13
+ param :remote_name
14
+ param :remote_url
15
+ runner RemoteAddSubcommand
16
+ end
17
+ end
18
+
19
+ def run
20
+ # 'arguments' cannot be converted to Hash
21
+ add_remote arguments[:remote_name], arguments[:remote_url]
22
+ end
23
+
24
+ private
25
+
26
+ def validate_remote_name(name)
27
+ raise ThreeScaleToolbox::Error, 'remote name already exists.' if remotes.all.key?(name)
28
+ end
29
+
30
+ def validate_remote(remote_url_str)
31
+ # parsing url before trying to create client
32
+ # raises Invalid URL when syntax is incorrect
33
+ ThreeScaleToolbox::Helper.parse_uri(remote_url_str)
34
+ threescale_client(remote_url_str).list_services
35
+ rescue ThreeScale::API::HttpClient::ForbiddenError
36
+ raise ThreeScaleToolbox::Error, 'remote not valid'
37
+ end
38
+
39
+ def add_remote(remote_name, remote_url)
40
+ validate_remote_name remote_name
41
+ validate_remote remote_url
42
+ remotes.add_uri(remote_name, remote_url)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,29 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module RemoteCommand
4
+ class RemoteListSubcommand < Cri::CommandRunner
5
+ include ThreeScaleToolbox::Command
6
+
7
+ def self.command
8
+ Cri::Command.define do
9
+ name 'list'
10
+ usage 'list'
11
+ summary 'remote list'
12
+ description 'List all defined remotes'
13
+ runner RemoteListSubcommand
14
+ end
15
+ end
16
+
17
+ def run
18
+ if remotes.all.empty?
19
+ puts 'Empty remote list.'
20
+ else
21
+ remotes.all.each do |name, remote|
22
+ puts "#{name} #{remote[:endpoint]} #{remote[:authentication]}"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module RemoteCommand
4
+ class RemoteRemoveSubcommand < Cri::CommandRunner
5
+ include ThreeScaleToolbox::Command
6
+
7
+ def self.command
8
+ Cri::Command.define do
9
+ name 'remove'
10
+ usage 'remove <name>'
11
+ summary 'remote remove'
12
+ description 'Remove remote from list'
13
+ param :remote_name
14
+ runner RemoteRemoveSubcommand
15
+ end
16
+ end
17
+
18
+ def run
19
+ remotes.delete(arguments[:remote_name]) do |el|
20
+ raise ThreeScaleToolbox::Error, "could not remove remote '#{el}'"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module RemoteCommand
4
+ class RemoteRenameSubcommand < Cri::CommandRunner
5
+ include ThreeScaleToolbox::Command
6
+
7
+ def self.command
8
+ Cri::Command.define do
9
+ name 'rename'
10
+ usage 'rename <old_name> <new_name>'
11
+ summary 'remote rename'
12
+ description 'Rename remote name'
13
+ param :remote_old_name
14
+ param :remote_new_name
15
+ runner RemoteRenameSubcommand
16
+ end
17
+ end
18
+
19
+ def run
20
+ # 'arguments' cannot be converted to Hash
21
+ rename_remote arguments[:remote_old_name], arguments[:remote_new_name]
22
+ end
23
+
24
+ private
25
+
26
+ def validate_remote_old_name(name)
27
+ raise ThreeScaleToolbox::Error, "Could not rename, old name '#{name}' does not exist." unless remotes.all.key?(name)
28
+ end
29
+
30
+ def validate_remote_new_name(name)
31
+ raise ThreeScaleToolbox::Error, "Could not rename, new name '#{name}' already exists." if remotes.all.key?(name)
32
+ end
33
+
34
+ def rename_remote(remote_old_name, remote_new_name)
35
+ validate_remote_old_name remote_old_name
36
+ validate_remote_new_name remote_new_name
37
+ remotes.add(remote_new_name, remotes.delete(remote_old_name))
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -5,13 +5,13 @@ require '3scale_toolbox/commands/update_command/update_service'
5
5
  module ThreeScaleToolbox
6
6
  module Commands
7
7
  module UpdateCommand
8
- extend ThreeScaleToolbox::Command
8
+ include ThreeScaleToolbox::Command
9
9
  def self.command
10
10
  Cri::Command.define do
11
11
  name 'update'
12
- usage 'update <command> [options]'
13
- summary '3scale update command'
14
- description '3scale update command.'
12
+ usage 'update <sub-command> [options]'
13
+ summary 'update super command'
14
+ description 'Update 3scale entities between tenants'
15
15
  end
16
16
  end
17
17
  add_subcommand(UpdateServiceSubcommand)
@@ -4,253 +4,63 @@ require '3scale_toolbox/base_command'
4
4
  module ThreeScaleToolbox
5
5
  module Commands
6
6
  module UpdateCommand
7
- module UpdateServiceSubcommand
8
- extend ThreeScaleToolbox::Command
7
+ class UpdateServiceSubcommand < Cri::CommandRunner
8
+ include ThreeScaleToolbox::Command
9
+
9
10
  def self.command
10
11
  Cri::Command.define do
11
12
  name 'service'
12
13
  usage 'service [opts] -s <src> -d <dst> <src_service_id> <dst_service_id>'
13
- summary 'Update service'
14
- description 'Will update existing service, update proxy settings, metrics, methods, application plans and mapping rules.'
15
-
16
- required :s, :source, '3scale source instance. Format: "http[s]://<provider_key>@3scale_url"'
17
- required :d, :destination, '3scale target instance. Format: "http[s]://<provider_key>@3scale_url"'
18
- option :t, 'target_system_name', 'Target system name', argument: :required
19
- flag :f, :force, 'Overwrites the mapping rules by deleting all rules from target service first'
20
- flag :r, 'rules-only', 'Updates only the mapping rules'
21
-
22
- run do |opts, args, _|
23
- UpdateServiceSubcommand.run opts, args
24
- end
14
+ summary 'update service'
15
+ description 'Update existing service, update proxy settings, metrics, methods, application plans and mapping rules.'
16
+
17
+ option :s, :source, '3scale source instance. Url or remote name', argument: :required
18
+ option :d, :destination, '3scale target instance. Url or remote name', argument: :required
19
+ option :t, 'target_system_name', 'Target system name', argument: :required
20
+ flag :f, :force, 'Overwrites the mapping rules by deleting all rules from target service first'
21
+ flag :r, 'rules-only', 'Updates only the mapping rules'
22
+ param :src_service_id
23
+ param :dst_service_id
24
+
25
+ runner UpdateServiceSubcommand
25
26
  end
26
27
  end
27
28
 
28
- def self.exit_with_message(message)
29
- puts message
30
- exit 1
31
- end
32
-
33
- def self.fetch_required_option(options, key)
34
- options.fetch(key) { exit_with_message "error: Missing argument #{key}" }
35
- end
36
-
37
- class ServiceUpdater
38
- attr_reader :source_client, :target_client, :source_service_id, :target_service_id, :target_system_name
39
-
40
- def initialize (source, source_service_id, destination, target_service_id, insecure, system_name)
41
- @source_client = ThreeScale::API.new(
42
- endpoint: endpoint_from_url(source),
43
- provider_key: provider_key_from_url(source),
44
- verify_ssl: !insecure
45
- )
46
- @target_client = ThreeScale::API.new(
47
- endpoint: endpoint_from_url(destination),
48
- provider_key: provider_key_from_url(destination),
49
- verify_ssl: !insecure
50
- )
51
- @source_service_id = source_service_id
52
- @target_service_id = target_service_id
53
- @target_system_name = system_name
54
- end
55
-
56
- def compare_hashes(first, second, keys)
57
- keys.map{ |key| first.fetch(key) } == keys.map{ |key| second.fetch(key) }
58
- end
59
-
60
- def provider_key_from_url(url)
61
- URI(url).user
62
- end
63
-
64
- def endpoint_from_url(url)
65
- uri = URI(url)
66
- uri.user = nil
67
-
68
- uri.to_s
69
- end
70
-
71
- # system name only included when specified from options
72
- def target_service_params(source)
73
- target_service = source.select do |k, v|
74
- Commands.service_valid_params.include?(k) \
75
- && k != 'system_name' \
76
- && v
77
- end
78
- target_service.tap do |hash|
79
- hash['system_name'] = target_system_name unless target_system_name.nil?
80
- end
81
- end
82
-
83
- def source_metrics
84
- @source_metrics ||= source_client.list_metrics(source_service_id)
85
- end
86
-
87
- def metrics_mapping
88
- @metrics_mapping ||= target_client.list_metrics(target_service_id).map do |target|
89
- metric = source_metrics.find{|metric| metric.fetch('system_name') == target.fetch('system_name') }
90
- metric ||= {}
91
-
92
- [metric['id'], target['id']]
93
- end.to_h
94
- end
95
-
96
- def copy_service_settings
97
- source_service = source_client.show_service(source_service_id)
98
- puts "updating service settings for service id #{target_service_id}..."
99
- target_update_response = target_client.update_service(target_service_id, target_service_params(source_service))
100
- raise "Service has not been saved. Errors: #{target_update_response['errors']}" unless target_update_response['errors'].nil?
101
- end
102
-
103
- def copy_proxy_settings
104
- puts "updating proxy configuration for service id #{target_service_id}..."
105
- proxy = source_client.show_proxy(source_service_id)
106
- target_client.update_proxy(target_service_id, proxy)
107
- puts "updated proxy of #{target_service_id} to match the source #{source_service_id}"
108
- end
109
-
110
- def copy_metrics_and_methods
111
- target_metrics = target_client.list_metrics(target_service_id)
112
-
113
- source_hits = source_metrics.find{ |metric| metric['system_name'] == 'hits' } or raise 'missing hits metric'
114
- target_hits = target_metrics.find{ |metric| metric['system_name'] == 'hits' } or raise 'missing hits metric'
115
-
116
- source_methods = source_client.list_methods(source_service_id, source_hits['id'])
117
- target_methods = target_client.list_methods(target_service_id, target_hits['id'])
118
-
119
- puts "source service hits metric #{source_hits['id']} has #{source_methods.size} methods"
120
- puts "target service hits metric #{target_hits['id']} has #{target_methods.size} methods"
121
-
122
- missing_methods = source_methods.reject { |source_method| target_methods.find{|target_method| compare_hashes(source_method, target_method, ['system_name']) } }
123
-
124
- puts "creating #{missing_methods.size} missing methods on target service..."
125
- missing_methods.each do |method|
126
- target = { friendly_name: method['friendly_name'], system_name: method['system_name'] }
127
- target_client.create_method(target_service_id, target_hits['id'], target)
128
- end
129
-
130
- target_metrics = target_client.list_metrics(target_service_id)
131
-
132
- puts "source service has #{source_metrics.size} metrics"
133
- puts "target service has #{target_metrics.size} metrics"
134
-
135
- missing_metrics = source_metrics.reject { |source_metric| target_metrics.find{|target_metric| compare_hashes(source_metric, target_metric, ['system_name']) } }
136
-
137
- missing_metrics.map do |metric|
138
- metric.delete('links')
139
- target_client.create_metric(target_service_id, metric)
140
- end
141
-
142
- puts "created #{missing_metrics.size} metrics on the target service"
29
+ def run
30
+ source_service = Entities::Service.new(
31
+ id: arguments[:src_service_id],
32
+ remote: threescale_client(fetch_required_option(:source))
33
+ )
34
+ update_service = Entities::Service.new(
35
+ id: arguments[:dst_service_id],
36
+ remote: threescale_client(fetch_required_option(:destination))
37
+ )
38
+ system_name = options[:target_system_name]
39
+ context = create_context(source_service, update_service)
40
+
41
+ tasks = []
42
+ unless options[:'rules-only']
43
+ tasks << Tasks::UpdateServiceSettingsTask.new(context.merge(target_name: system_name))
44
+ tasks << Tasks::CopyServiceProxyTask.new(context)
45
+ tasks << Tasks::CopyMethodsTask.new(context)
46
+ tasks << Tasks::CopyMetricsTask.new(context)
47
+ tasks << Tasks::CopyApplicationPlansTask.new(context)
48
+ tasks << Tasks::CopyLimitsTask.new(context)
143
49
  end
50
+ tasks << Tasks::DestroyMappingRulesTask.new(context) if options[:force]
51
+ tasks << Tasks::CopyMappingRulesTask.new(context)
144
52
 
145
- def copy_application_plans
146
- source_plans = source_client.list_service_application_plans(source_service_id)
147
- target_plans = target_client.list_service_application_plans(target_service_id)
148
-
149
- puts "source service has #{source_plans.size} application plans"
150
- puts "target service has #{target_plans.size} application plans"
151
-
152
- missing_application_plans = source_plans.reject { |source_plan| target_plans.find{|target_plan| source_plan.fetch('system_name') == target_plan.fetch('system_name') } }
153
-
154
- puts "creating #{missing_application_plans.size} missing application plans..."
155
-
156
- missing_application_plans.each do |plan|
157
- plan.delete('links')
158
- plan.delete('default') # TODO: handle default plans
159
-
160
- if plan.delete('custom') # TODO: what to do with custom plans?
161
- puts "skipping custom plan #{plan}"
162
- else
163
- target_client.create_application_plan(target_service_id, plan)
164
- end
165
- end
166
-
167
- puts "updating limits for application plans..."
168
-
169
- application_plan_mapping = target_client.list_service_application_plans(target_service_id).map do |plan_target|
170
- plan = source_plans.find{|plan| plan.fetch('system_name') == plan_target.fetch('system_name') }
171
- plan ||= {}
172
- [plan['id'], plan_target['id']]
173
- end.to_h.reject { |key, value| !key }
174
-
175
- application_plan_mapping.each do |source_id, target_id|
176
- source_limits = source_client.list_application_plan_limits(source_id)
177
- target_limits = target_client.list_application_plan_limits(target_id)
178
-
179
- missing_limits = source_limits.reject { |limit| target_limits.find{|limit_target| limit.fetch('period') == limit_target.fetch('period') } }
180
-
181
- puts "target application plan #{target_id} is missing #{missing_limits.size} from the source plan #{source_id}"
182
-
183
- missing_limits.each do |limit|
184
- limit.delete('links')
185
- target_client.create_application_plan_limit(target_id, metrics_mapping.fetch(limit.fetch('metric_id')), limit)
186
- end
187
-
188
- end
189
- end
190
-
191
- def copy_mapping_rules force_mapping_rules
192
- source_mapping_rules = source_client.list_mapping_rules(source_service_id)
193
- target_mapping_rules = target_client.list_mapping_rules(target_service_id)
194
-
195
- puts "the source service has #{source_mapping_rules.size} mapping rules"
196
- puts "the target has #{target_mapping_rules.size} mapping rules"
197
-
198
- if force_mapping_rules
199
- puts "force mode was chosen, deleting existing mapping rules on target service..."
200
- target_mapping_rules.each do |rule|
201
- target_client.delete_mapping_rule(target_service_id, rule['id'])
202
- end
203
- missing_mapping_rules = source_mapping_rules
204
- else
205
- unique_target_mapping_rules = target_mapping_rules.dup
206
-
207
- missing_mapping_rules = source_mapping_rules.reject do |mapping_rule|
208
- matching_metric = unique_target_mapping_rules.find do |target|
209
- compare_hashes(mapping_rule, target, %w(pattern http_method delta)) &&
210
- metrics_mapping.fetch(mapping_rule.fetch('metric_id')) == target.fetch('metric_id')
211
- end
212
-
213
- unique_target_mapping_rules.delete(matching_metric)
214
- end
215
- end
216
-
217
- puts "missing #{missing_mapping_rules.size} mapping rules"
218
-
219
- missing_mapping_rules.each do |mapping_rule|
220
- mapping_rule.delete('links')
221
- mapping_rule['metric_id'] = metrics_mapping.fetch(mapping_rule.delete('metric_id'))
222
- target_client.create_mapping_rule(target_service_id, mapping_rule)
223
- end
224
- puts "created #{missing_mapping_rules.size} mapping rules"
225
- end
226
-
227
- def update_service force_mapping_rules=false
228
- copy_service_settings
229
- copy_proxy_settings
230
- copy_metrics_and_methods
231
- copy_application_plans
232
- copy_mapping_rules force_mapping_rules
233
- end
53
+ # run tasks
54
+ tasks.each(&:call)
234
55
  end
235
56
 
236
- def self.run(opts, args)
237
- source = fetch_required_option(opts, :source)
238
- destination = fetch_required_option(opts, :destination)
239
- insecure = opts[:insecure] || false
240
- exit_with_message 'error: missing source_service_id argument' if args.empty?
241
- exit_with_message 'error: missing target_service_id argument' if args.size < 2
242
- source_service_id = args[0]
243
- target_service_id = args[1]
244
- force_update = opts[:force] || false
245
- rules_only = opts[:'rules-only'] || false
246
- system_name = opts[:target_system_name]
247
- updater = ServiceUpdater.new(source, source_service_id, destination, target_service_id, insecure, system_name)
57
+ private
248
58
 
249
- if rules_only
250
- updater.copy_mapping_rules force_update
251
- else
252
- updater.update_service force_update
253
- end
59
+ def create_context(source, target)
60
+ {
61
+ source: source,
62
+ target: target
63
+ }
254
64
  end
255
65
  end
256
66
  end