3scale_toolbox 0.5.1 → 0.6.0

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