3scale_toolbox 0.11.0 → 0.12.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.
- checksums.yaml +4 -4
- data/3scale_toolbox.gemspec +42 -0
- data/LICENSE +201 -0
- data/NOTICE +15 -0
- data/README.md +8 -0
- data/lib/3scale_toolbox.rb +1 -0
- data/lib/3scale_toolbox/commands/application_command/apply_command.rb +21 -6
- data/lib/3scale_toolbox/commands/application_command/create_command.rb +3 -1
- data/lib/3scale_toolbox/commands/copy_command/copy_service.rb +5 -0
- data/lib/3scale_toolbox/commands/import_command/openapi.rb +5 -3
- data/lib/3scale_toolbox/commands/import_command/openapi/create_activedocs_step.rb +10 -2
- data/lib/3scale_toolbox/commands/import_command/openapi/create_method_step.rb +13 -6
- data/lib/3scale_toolbox/commands/import_command/openapi/method.rb +5 -0
- data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +4 -0
- data/lib/3scale_toolbox/commands/import_command/openapi/threescale_api_spec.rb +2 -1
- data/lib/3scale_toolbox/commands/import_command/openapi/update_service_proxy_step.rb +12 -5
- data/lib/3scale_toolbox/commands/metrics_command/list_command.rb +1 -8
- data/lib/3scale_toolbox/commands/plans_command/apply_command.rb +8 -7
- data/lib/3scale_toolbox/commands/plans_command/create_command.rb +0 -2
- data/lib/3scale_toolbox/commands/plans_command/export/read_plan_methods_step.rb +0 -3
- data/lib/3scale_toolbox/commands/plans_command/export/read_plan_metrics_step.rb +0 -2
- data/lib/3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step.rb +2 -1
- data/lib/3scale_toolbox/commands/plans_command/export/step.rb +0 -2
- data/lib/3scale_toolbox/commands/plans_command/import/create_or_update_app_plan_step.rb +8 -3
- data/lib/3scale_toolbox/commands/plans_command/import/import_plan_metrics_step.rb +0 -3
- data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +9 -2
- data/lib/3scale_toolbox/commands/plans_command/import/step.rb +5 -1
- data/lib/3scale_toolbox/commands/proxy_config_command/promote_command.rb +21 -5
- data/lib/3scale_toolbox/entities/account.rb +44 -4
- data/lib/3scale_toolbox/entities/activedocs.rb +1 -1
- data/lib/3scale_toolbox/entities/application.rb +21 -13
- data/lib/3scale_toolbox/entities/application_plan.rb +13 -12
- data/lib/3scale_toolbox/entities/base_entity.rb +1 -1
- data/lib/3scale_toolbox/entities/method.rb +1 -1
- data/lib/3scale_toolbox/entities/metric.rb +1 -1
- data/lib/3scale_toolbox/entities/service.rb +30 -15
- data/lib/3scale_toolbox/remotes.rb +1 -1
- data/lib/3scale_toolbox/resource_reader.rb +5 -2
- data/lib/3scale_toolbox/swagger/swagger.rb +5 -3
- data/lib/3scale_toolbox/tasks/copy_activedocs_task.rb +27 -9
- data/lib/3scale_toolbox/tasks/copy_limits_task.rb +4 -1
- data/lib/3scale_toolbox/tasks/copy_mapping_rules_task.rb +4 -1
- data/lib/3scale_toolbox/tasks/copy_methods_task.rb +20 -16
- data/lib/3scale_toolbox/tasks/copy_metrics_task.rb +14 -14
- data/lib/3scale_toolbox/tasks/copy_pricingrules_task.rb +4 -1
- data/lib/3scale_toolbox/tasks/copy_task.rb +40 -0
- data/lib/3scale_toolbox/version.rb +1 -1
- data/licenses.xml +303 -0
- metadata +8 -4
@@ -16,37 +16,37 @@ module ThreeScaleToolbox
|
|
16
16
|
# * User_key (API key)
|
17
17
|
# * App_id (from app_id/app_key pair)
|
18
18
|
# * Client ID (for OAuth and OpenID Connect authentication modes)
|
19
|
-
def find(remote:, ref:)
|
20
|
-
app = find_by_user_key(remote, ref)
|
19
|
+
def find(remote:, service_id: nil, ref:)
|
20
|
+
app = find_by_user_key(remote, service_id, ref)
|
21
21
|
return app unless app.nil?
|
22
22
|
|
23
|
-
app = find_by_app_id(remote, ref)
|
23
|
+
app = find_by_app_id(remote, service_id, ref)
|
24
24
|
return app unless app.nil?
|
25
25
|
|
26
|
-
app = find_by_id(remote, ref)
|
26
|
+
app = find_by_id(remote, service_id, ref)
|
27
27
|
return app unless app.nil?
|
28
28
|
|
29
29
|
nil
|
30
30
|
end
|
31
31
|
|
32
|
-
def find_by_id(remote, id)
|
33
|
-
generic_find(remote, :id, id)
|
32
|
+
def find_by_id(remote, service_id, id)
|
33
|
+
generic_find(remote, service_id, :id, id)
|
34
34
|
end
|
35
35
|
|
36
|
-
def find_by_user_key(remote, user_key)
|
37
|
-
generic_find(remote, :user_key, user_key)
|
36
|
+
def find_by_user_key(remote, service_id, user_key)
|
37
|
+
generic_find(remote, service_id, :user_key, user_key)
|
38
38
|
end
|
39
39
|
|
40
|
-
def find_by_app_id(remote, app_id)
|
41
|
-
generic_find(remote, :application_id, app_id)
|
40
|
+
def find_by_app_id(remote, service_id, app_id)
|
41
|
+
generic_find(remote, service_id, :application_id, app_id)
|
42
42
|
end
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
def generic_find(remote, type, ref)
|
46
|
+
def generic_find(remote, service_id, type, ref)
|
47
47
|
# find_application criteria only accepts one parameter.
|
48
48
|
# Otherwise unexpected behavior
|
49
|
-
attrs = remote.find_application(type => ref)
|
49
|
+
attrs = remote.find_application(service_id: service_id, type => ref)
|
50
50
|
if (errors = attrs['errors'])
|
51
51
|
raise ThreeScaleToolbox::ThreeScaleApiError.new('Application find error', errors)
|
52
52
|
end
|
@@ -60,7 +60,7 @@ module ThreeScaleToolbox
|
|
60
60
|
attr_reader :id, :remote
|
61
61
|
|
62
62
|
def initialize(id:, remote:, attrs: nil)
|
63
|
-
@id = id
|
63
|
+
@id = id.to_i
|
64
64
|
@remote = remote
|
65
65
|
@attrs = attrs
|
66
66
|
end
|
@@ -81,6 +81,8 @@ module ThreeScaleToolbox
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def resume
|
84
|
+
return attrs if live?
|
85
|
+
|
84
86
|
new_attrs = remote.resume_application(account_id, id)
|
85
87
|
if (errors = new_attrs['errors'])
|
86
88
|
raise ThreeScaleToolbox::ThreeScaleApiError.new('Application has not been resumed', errors)
|
@@ -92,6 +94,8 @@ module ThreeScaleToolbox
|
|
92
94
|
end
|
93
95
|
|
94
96
|
def suspend
|
97
|
+
return attrs unless live?
|
98
|
+
|
95
99
|
new_attrs = remote.suspend_application(account_id, id)
|
96
100
|
if (errors = new_attrs['errors'])
|
97
101
|
raise ThreeScaleToolbox::ThreeScaleApiError.new('Application has not been suspended', errors)
|
@@ -106,6 +110,10 @@ module ThreeScaleToolbox
|
|
106
110
|
remote.delete_application account_id, id
|
107
111
|
end
|
108
112
|
|
113
|
+
def live?
|
114
|
+
attrs.fetch('state') == 'live'
|
115
|
+
end
|
116
|
+
|
109
117
|
private
|
110
118
|
|
111
119
|
def account_id
|
@@ -39,7 +39,7 @@ module ThreeScaleToolbox
|
|
39
39
|
attr_reader :id, :service, :remote
|
40
40
|
|
41
41
|
def initialize(id:, service:, attrs: nil)
|
42
|
-
@id = id
|
42
|
+
@id = id.to_i
|
43
43
|
@service = service
|
44
44
|
@remote = service.remote
|
45
45
|
@attrs = attrs
|
@@ -50,6 +50,8 @@ module ThreeScaleToolbox
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def update(plan_attrs)
|
53
|
+
return attrs if update_plan_attrs(plan_attrs).empty?
|
54
|
+
|
53
55
|
new_attrs = remote.update_application_plan(service.id, id,
|
54
56
|
update_plan_attrs(plan_attrs))
|
55
57
|
if (errors = new_attrs['errors'])
|
@@ -170,6 +172,10 @@ module ThreeScaleToolbox
|
|
170
172
|
end
|
171
173
|
end
|
172
174
|
|
175
|
+
def published?
|
176
|
+
attrs.fetch('state') == 'published'
|
177
|
+
end
|
178
|
+
|
173
179
|
private
|
174
180
|
|
175
181
|
def read_plan_attrs
|
@@ -181,17 +187,12 @@ module ThreeScaleToolbox
|
|
181
187
|
plan_attrs
|
182
188
|
end
|
183
189
|
|
184
|
-
def update_plan_attrs(
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
# plans are created by default in hidden state
|
191
|
-
# If published is required, 'state_event' attr has to be added
|
192
|
-
state = new_plan_attrs.delete('state')
|
193
|
-
new_plan_attrs['state_event'] = 'publish' if state == 'published'
|
194
|
-
new_plan_attrs['state_event'] = 'hide' if state == 'hidden'
|
190
|
+
def update_plan_attrs(update_attrs)
|
191
|
+
new_attrs = update_attrs.reject { |key, _| %w[id links system_name].include? key }
|
192
|
+
new_attrs.tap do |params|
|
193
|
+
state = params.delete('state')
|
194
|
+
params['state_event'] = 'publish' if state == 'published' && !published?
|
195
|
+
params['state_event'] = 'hide' if state == 'hidden' && published?
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
@@ -66,7 +66,7 @@ module ThreeScaleToolbox
|
|
66
66
|
attr_reader :id, :remote
|
67
67
|
|
68
68
|
def initialize(id:, remote:, attrs: nil)
|
69
|
-
@id = id
|
69
|
+
@id = id.to_i
|
70
70
|
@remote = remote
|
71
71
|
@attrs = attrs
|
72
72
|
end
|
@@ -95,21 +95,18 @@ module ThreeScaleToolbox
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def metrics
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
98
|
+
# cache result to reuse
|
99
|
+
metric_and_method_list = metrics_and_methods
|
100
|
+
hits_metric_obj = hits_metric(metric_and_method_list)
|
101
|
+
hits_id = hits_metric_obj.fetch('id')
|
102
102
|
|
103
|
-
|
103
|
+
ThreeScaleToolbox::Helper.array_difference(metric_and_method_list, methods(hits_id)) do |metric, method|
|
104
|
+
ThreeScaleToolbox::Helper.compare_hashes(metric, method, %w[id])
|
105
|
+
end
|
104
106
|
end
|
105
107
|
|
106
108
|
def hits
|
107
|
-
hits_metric
|
108
|
-
metric['system_name'] == 'hits'
|
109
|
-
end
|
110
|
-
raise ThreeScaleToolbox::Error, 'missing hits metric' if hits_metric.nil?
|
111
|
-
|
112
|
-
hits_metric
|
109
|
+
hits_metric(metrics_and_methods)
|
113
110
|
end
|
114
111
|
|
115
112
|
def methods(parent_metric_id)
|
@@ -121,6 +118,15 @@ module ThreeScaleToolbox
|
|
121
118
|
service_methods
|
122
119
|
end
|
123
120
|
|
121
|
+
def metrics_and_methods
|
122
|
+
m_m = remote.list_metrics id
|
123
|
+
if m_m.respond_to?(:has_key?) && (errors = m_m['errors'])
|
124
|
+
raise ThreeScaleToolbox::ThreeScaleApiError.new('Service metrics not read', errors)
|
125
|
+
end
|
126
|
+
|
127
|
+
m_m
|
128
|
+
end
|
129
|
+
|
124
130
|
def plans
|
125
131
|
service_plans = remote.list_service_application_plans id
|
126
132
|
if service_plans.respond_to?(:has_key?) && (errors = service_plans['errors'])
|
@@ -174,9 +180,7 @@ module ThreeScaleToolbox
|
|
174
180
|
end
|
175
181
|
|
176
182
|
tenant_activedocs.select do |activedoc|
|
177
|
-
|
178
|
-
# activedocs endpoints return service_id as integers
|
179
|
-
activedoc['service_id'] == id.to_i
|
183
|
+
activedoc['service_id'] == id
|
180
184
|
end
|
181
185
|
end
|
182
186
|
|
@@ -245,8 +249,19 @@ module ThreeScaleToolbox
|
|
245
249
|
end
|
246
250
|
end
|
247
251
|
|
252
|
+
def ==(other)
|
253
|
+
remote.http_client.endpoint == other.remote.http_client.endpoint && id == other.id
|
254
|
+
end
|
255
|
+
|
248
256
|
private
|
249
257
|
|
258
|
+
def hits_metric(metric_list)
|
259
|
+
hits_metric = metric_list.find { |metric| metric['system_name'] == 'hits' }
|
260
|
+
raise ThreeScaleToolbox::Error, 'missing hits metric' if hits_metric.nil?
|
261
|
+
|
262
|
+
hits_metric
|
263
|
+
end
|
264
|
+
|
250
265
|
def service_attrs
|
251
266
|
svc = remote.show_service id
|
252
267
|
if (errors = svc['errors'])
|
@@ -27,8 +27,11 @@ module ThreeScaleToolbox
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# Detect format from file extension
|
30
|
-
def read_file(
|
31
|
-
File.
|
30
|
+
def read_file(filename)
|
31
|
+
raise ThreeScaleToolbox::Error, "File not found: #{filename} " unless File.file?(filename)
|
32
|
+
raise ThreeScaleToolbox::Error, "File not readable: #{filename} " unless File.readable?(filename)
|
33
|
+
|
34
|
+
File.read(filename)
|
32
35
|
end
|
33
36
|
|
34
37
|
def read_stdin(_resource)
|
@@ -23,12 +23,13 @@ module ThreeScaleToolbox
|
|
23
23
|
end
|
24
24
|
|
25
25
|
class Operation
|
26
|
-
attr_reader :verb, :operation_id, :path
|
26
|
+
attr_reader :verb, :operation_id, :path, :description
|
27
27
|
|
28
|
-
def initialize(verb:, operation_id:, path:)
|
28
|
+
def initialize(verb:, operation_id:, path:, description:)
|
29
29
|
@verb = verb
|
30
30
|
@operation_id = operation_id
|
31
31
|
@path = path
|
32
|
+
@description = description
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
@@ -83,7 +84,8 @@ module ThreeScaleToolbox
|
|
83
84
|
path_obj.flat_map do |method, operation|
|
84
85
|
next unless %w[get head post put patch delete trace options].include? method
|
85
86
|
|
86
|
-
Operation.new(verb: method, path: path,
|
87
|
+
Operation.new(verb: method, path: path, description: operation['description'],
|
88
|
+
operation_id: operation['operationId'])
|
87
89
|
end.compact
|
88
90
|
end
|
89
91
|
end
|
@@ -6,17 +6,35 @@ module ThreeScaleToolbox
|
|
6
6
|
def call
|
7
7
|
puts 'copying all service ActiveDocs'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
source.activedocs.each(&method(:apply_target_activedoc))
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def apply_target_activedoc(attrs)
|
15
|
+
activedocs = Entities::ActiveDocs.find_by_system_name(remote: target.remote,
|
16
|
+
system_name: attrs['system_name'])
|
17
|
+
if activedocs.nil?
|
18
|
+
Entities::ActiveDocs.create(remote: target.remote, attrs: create_attrs(attrs))
|
19
|
+
elsif activedocs.attrs.fetch('service_id') == target.id
|
20
|
+
activedocs.update(update_attrs(attrs))
|
21
|
+
else
|
22
|
+
# activedocs with same system_name exists, but now owned by target service
|
23
|
+
new_attrs = create_attrs(attrs)
|
24
|
+
new_attrs['system_name'] = "#{attrs['system_name']}#{target.id}"
|
25
|
+
Entities::ActiveDocs.create(remote: target.remote, attrs: new_attrs)
|
15
26
|
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_attrs(old_attrs)
|
30
|
+
create_attrs(old_attrs)
|
31
|
+
end
|
16
32
|
|
17
|
-
|
18
|
-
|
19
|
-
|
33
|
+
def create_attrs(old_attrs)
|
34
|
+
# keep same system_name
|
35
|
+
new_attrs = old_attrs.reject { |key, _| %w[id created_at updated_at].include? key }
|
36
|
+
new_attrs.tap do |attrs|
|
37
|
+
attrs['service_id'] = target.id
|
20
38
|
end
|
21
39
|
end
|
22
40
|
end
|
@@ -5,7 +5,6 @@ module ThreeScaleToolbox
|
|
5
5
|
include Helper
|
6
6
|
|
7
7
|
def call
|
8
|
-
metrics_map = metrics_mapping(source.metrics, target.metrics)
|
9
8
|
plan_mapping = application_plan_mapping(source.plans, target.plans)
|
10
9
|
plan_mapping.each do |plan_id, target_plan|
|
11
10
|
source_plan = ThreeScaleToolbox::Entities::ApplicationPlan.new(id: plan_id, service: source)
|
@@ -22,6 +21,10 @@ module ThreeScaleToolbox
|
|
22
21
|
|
23
22
|
private
|
24
23
|
|
24
|
+
def metrics_map
|
25
|
+
@metrics_map ||= metrics_mapping(source_metrics_and_methods, target_metrics_and_methods)
|
26
|
+
end
|
27
|
+
|
25
28
|
def missing_limits(source_limits, target_limits, metrics_map)
|
26
29
|
ThreeScaleToolbox::Helper.array_difference(source_limits, target_limits) do |limit, target|
|
27
30
|
ThreeScaleToolbox::Helper.compare_hashes(limit, target, ['period']) &&
|
@@ -5,7 +5,6 @@ module ThreeScaleToolbox
|
|
5
5
|
include Helper
|
6
6
|
|
7
7
|
def call
|
8
|
-
metrics_map = metrics_mapping(source.metrics, target.metrics)
|
9
8
|
missing_rules = missing_mapping_rules(source.mapping_rules,
|
10
9
|
target.mapping_rules, metrics_map)
|
11
10
|
missing_rules.each do |mapping_rule|
|
@@ -18,6 +17,10 @@ module ThreeScaleToolbox
|
|
18
17
|
|
19
18
|
private
|
20
19
|
|
20
|
+
def metrics_map
|
21
|
+
@metrics_map ||= metrics_mapping(source_metrics_and_methods, target_metrics_and_methods)
|
22
|
+
end
|
23
|
+
|
21
24
|
def missing_mapping_rules(source_rules, target_rules, metrics_map)
|
22
25
|
ThreeScaleToolbox::Helper.array_difference(source_rules, target_rules) do |source_rule, target_rule|
|
23
26
|
ThreeScaleToolbox::Helper.compare_hashes(source_rule, target_rule, %w[pattern http_method delta]) &&
|
@@ -4,26 +4,30 @@ module ThreeScaleToolbox
|
|
4
4
|
include CopyTask
|
5
5
|
|
6
6
|
def call
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
puts "target service hits metric #{target_hits_id} has #{target_methods.size} methods"
|
13
|
-
missing = missing_methods(source_methods, target_methods).each do |method|
|
14
|
-
Entities::Method.create(
|
15
|
-
service: target,
|
16
|
-
parent_id: target_hits_id,
|
17
|
-
attrs: ThreeScaleToolbox::Helper.filter_params(%w[friendly_name system_name], method)
|
18
|
-
)
|
19
|
-
end
|
20
|
-
puts "created #{missing.size} missing methods on target service"
|
7
|
+
puts "original service hits metric #{source_hits.fetch('id')} has #{source_methods.size} methods"
|
8
|
+
puts "target service hits metric #{target_hits.fetch('id')} has #{target_methods.size} methods"
|
9
|
+
missing_methods.each(&method(:create_method))
|
10
|
+
puts "created #{missing_methods.size} missing methods on target service"
|
11
|
+
invalidate_target_methods if missing_methods.size.positive?
|
21
12
|
end
|
22
13
|
|
23
14
|
private
|
24
15
|
|
25
|
-
def
|
26
|
-
|
16
|
+
def create_method(method)
|
17
|
+
Entities::Method.create(
|
18
|
+
service: target,
|
19
|
+
parent_id: target_hits.fetch('id'),
|
20
|
+
attrs: ThreeScaleToolbox::Helper.filter_params(%w[friendly_name system_name], method)
|
21
|
+
)
|
22
|
+
rescue ThreeScaleToolbox::ThreeScaleApiError => e
|
23
|
+
raise e unless ThreeScaleToolbox::Helper.system_name_already_taken_error?(e.apierrors)
|
24
|
+
|
25
|
+
warn "[WARN] method #{method.fetch('system_name')} not created. " \
|
26
|
+
'Metric with the same system_name exists.'
|
27
|
+
end
|
28
|
+
|
29
|
+
def missing_methods
|
30
|
+
@missing_methods ||= ThreeScaleToolbox::Helper.array_difference(source_methods, target_methods) do |method, target|
|
27
31
|
ThreeScaleToolbox::Helper.compare_hashes(method, target, ['system_name'])
|
28
32
|
end
|
29
33
|
end
|