3scale_toolbox 0.11.0 → 0.12.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -13,7 +13,14 @@ module ThreeScaleToolbox
|
|
13
13
|
end
|
14
14
|
|
15
15
|
existing_operations.each do |op|
|
16
|
-
|
16
|
+
method_attrs = methods_index.fetch(op.method['system_name'])
|
17
|
+
method = Entities::Method.new(
|
18
|
+
id: method_attrs.fetch('id'),
|
19
|
+
parent_id: hits_metric_id,
|
20
|
+
service: service
|
21
|
+
)
|
22
|
+
method.update(op.method)
|
23
|
+
op.set(:metric_id, method.id)
|
17
24
|
end
|
18
25
|
end
|
19
26
|
|
@@ -23,18 +30,18 @@ module ThreeScaleToolbox
|
|
23
30
|
@hits_metric_id ||= service.hits['id']
|
24
31
|
end
|
25
32
|
|
26
|
-
def
|
27
|
-
@
|
28
|
-
acc[method['system_name']] = method
|
33
|
+
def methods_index
|
34
|
+
@methods_index ||= service.methods(hits_metric_id).each_with_object({}) do |method, acc|
|
35
|
+
acc[method['system_name']] = method
|
29
36
|
end
|
30
37
|
end
|
31
38
|
|
32
39
|
def missing_operations
|
33
|
-
operations.reject { |op|
|
40
|
+
operations.reject { |op| methods_index.key? op.method['system_name'] }
|
34
41
|
end
|
35
42
|
|
36
43
|
def existing_operations
|
37
|
-
operations.select { |op|
|
44
|
+
operations.select { |op| methods_index.key? op.method['system_name'] }
|
38
45
|
end
|
39
46
|
end
|
40
47
|
end
|
@@ -6,6 +6,7 @@ module ThreeScaleToolbox
|
|
6
6
|
def method
|
7
7
|
{
|
8
8
|
'friendly_name' => friendly_name,
|
9
|
+
'description' => description,
|
9
10
|
'system_name' => system_name
|
10
11
|
}
|
11
12
|
end
|
@@ -21,6 +22,10 @@ module ThreeScaleToolbox
|
|
21
22
|
def operation_id
|
22
23
|
"#{operation[:verb]}#{operation[:path].gsub(/[^\w]/, '')}"
|
23
24
|
end
|
25
|
+
|
26
|
+
def description
|
27
|
+
String(operation[:description])
|
28
|
+
end
|
24
29
|
end
|
25
30
|
end
|
26
31
|
end
|
@@ -40,12 +40,9 @@ module ThreeScaleToolbox
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def add_api_backend_settings(settings)
|
43
|
-
return if
|
44
|
-
|
45
|
-
scheme = api_spec.schemes.first || 'https'
|
46
|
-
host = api_spec.host
|
43
|
+
return if private_base_url.nil?
|
47
44
|
|
48
|
-
settings[:api_backend] =
|
45
|
+
settings[:api_backend] = private_base_url
|
49
46
|
end
|
50
47
|
|
51
48
|
def add_security_proxy_settings(settings)
|
@@ -74,6 +71,16 @@ module ThreeScaleToolbox
|
|
74
71
|
raise ThreeScaleToolbox::Error, "Unexpected security in_f field #{in_f}"
|
75
72
|
end
|
76
73
|
end
|
74
|
+
|
75
|
+
def private_base_url
|
76
|
+
override_private_base_url || private_base_url_from_openapi
|
77
|
+
end
|
78
|
+
|
79
|
+
def private_base_url_from_openapi
|
80
|
+
return if api_spec.host.nil?
|
81
|
+
|
82
|
+
"#{api_spec.schemes.first || 'https'}://#{api_spec.host}"
|
83
|
+
end
|
77
84
|
end
|
78
85
|
end
|
79
86
|
end
|
@@ -33,18 +33,11 @@ module ThreeScaleToolbox
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def print_data
|
36
|
-
metrics.each do |metric|
|
36
|
+
service.metrics.each do |metric|
|
37
37
|
puts FIELDS_TO_SHOW.map { |field| metric.fetch(field, '(empty)') }.join("\t")
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
def metrics
|
42
|
-
hits_id = service.hits['id']
|
43
|
-
ThreeScaleToolbox::Helper.array_difference(service.metrics, service.methods(hits_id)) do |metric, method|
|
44
|
-
ThreeScaleToolbox::Helper.compare_hashes(metric, method, %w[id])
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
41
|
def service
|
49
42
|
@service ||= find_service
|
50
43
|
end
|
@@ -22,7 +22,6 @@ module ThreeScaleToolbox
|
|
22
22
|
option nil, 'cost-per-month', 'Cost per month', argument: :required, transform: method(:Float)
|
23
23
|
option nil, 'setup-fee', 'Setup fee', argument: :required, transform: method(:Float)
|
24
24
|
option nil, 'trial-period-days', 'Trial period days', argument: :required, transform: method(:Integer)
|
25
|
-
option nil, 'end-user-required', 'End user required. true or false', argument: :required, transform: ThreeScaleToolbox::Helper::BooleanTransformer.new
|
26
25
|
param :remote
|
27
26
|
param :service_ref
|
28
27
|
param :plan_ref
|
@@ -38,7 +37,7 @@ module ThreeScaleToolbox
|
|
38
37
|
plan = Entities::ApplicationPlan.create(service: service,
|
39
38
|
plan_attrs: create_plan_attrs)
|
40
39
|
else
|
41
|
-
plan.update(
|
40
|
+
plan.update(new_plan_attrs) unless new_plan_attrs.empty?
|
42
41
|
end
|
43
42
|
|
44
43
|
plan.make_default if option_default
|
@@ -65,12 +64,15 @@ module ThreeScaleToolbox
|
|
65
64
|
end
|
66
65
|
|
67
66
|
def create_plan_attrs
|
68
|
-
|
69
|
-
|
67
|
+
new_attrs = plan_basic_attrs.merge('name' => plan_ref) { |_key, oldval, _newval| oldval }
|
68
|
+
new_attrs.tap do |params|
|
69
|
+
params['system_name'] = plan_ref
|
70
|
+
params['state'] = 'published' if option_publish
|
71
|
+
end
|
70
72
|
end
|
71
73
|
|
72
|
-
def
|
73
|
-
plan_basic_attrs.tap do |params|
|
74
|
+
def new_plan_attrs
|
75
|
+
plan_basic_attrs.clone.tap do |params|
|
74
76
|
params['state'] = 'published' if option_publish
|
75
77
|
params['state'] = 'hidden' if option_hide
|
76
78
|
end
|
@@ -80,7 +82,6 @@ module ThreeScaleToolbox
|
|
80
82
|
{
|
81
83
|
'name' => options[:name],
|
82
84
|
'approval_required' => options[:'approval-required'],
|
83
|
-
'end_user_required' => options[:'end-user-required'],
|
84
85
|
'cost_per_month' => options[:'cost-per-month'],
|
85
86
|
'setup_fee' => options[:'setup-fee'],
|
86
87
|
'trial_period_days' => options[:'trial-period-days']
|
@@ -20,7 +20,6 @@ module ThreeScaleToolbox
|
|
20
20
|
option nil, 'cost-per-month', 'Cost per month', argument: :required, transform: method(:Float)
|
21
21
|
option nil, 'setup-fee', 'Setup fee', argument: :required, transform: method(:Float)
|
22
22
|
option nil, 'trial-period-days', 'Trial period days', argument: :required, transform: method(:Integer)
|
23
|
-
option nil, 'end-user-required', 'End user required. true or false', argument: :required, transform: ThreeScaleToolbox::Helper::BooleanTransformer.new
|
24
23
|
param :remote
|
25
24
|
param :service_ref
|
26
25
|
param :plan_name
|
@@ -56,7 +55,6 @@ module ThreeScaleToolbox
|
|
56
55
|
'name' => arguments[:plan_name],
|
57
56
|
'system_name' => options[:'system-name'],
|
58
57
|
'approval_required' => options[:'approval-required'],
|
59
|
-
'end_user_required' => options[:'end-user-required'],
|
60
58
|
'cost_per_month' => options[:'cost-per-month'],
|
61
59
|
'setup_fee' => options[:'setup-fee'],
|
62
60
|
'trial_period_days' => options[:'trial-period-days']
|
@@ -26,8 +26,6 @@ module ThreeScaleToolbox
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def filtered_limit_methods
|
29
|
-
# has to be filtered this way
|
30
|
-
# looking up in metrics list does not work. Metric list includes methods and metrics
|
31
29
|
result[:limits].select { |limit| limit.dig('metric', 'type') == 'method' }
|
32
30
|
end
|
33
31
|
|
@@ -40,7 +38,6 @@ module ThreeScaleToolbox
|
|
40
38
|
end
|
41
39
|
|
42
40
|
def filtered_pricing_rule_methods
|
43
|
-
# looking up in metrics list does not work. Metric list includes methods and metrics
|
44
41
|
result[:pricingrules].select { |limit| limit.dig('metric', 'type') == 'method' }
|
45
42
|
end
|
46
43
|
end
|
@@ -26,7 +26,6 @@ module ThreeScaleToolbox
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def filtered_limit_metrics
|
29
|
-
# looking up in metrics list does not work. Metric list includes methods and metrics
|
30
29
|
result[:limits].select { |limit| limit.dig('metric', 'type') == 'metric' }
|
31
30
|
end
|
32
31
|
|
@@ -39,7 +38,6 @@ module ThreeScaleToolbox
|
|
39
38
|
end
|
40
39
|
|
41
40
|
def filtered_pricing_rule_metrics
|
42
|
-
# looking up in metrics list does not work. Metric list includes methods and metrics
|
43
41
|
result[:pricingrules].select { |limit| limit.dig('metric', 'type') == 'metric' }
|
44
42
|
end
|
45
43
|
end
|
@@ -9,7 +9,8 @@ module ThreeScaleToolbox
|
|
9
9
|
# add metric system_name out of metric_id
|
10
10
|
def call
|
11
11
|
result[:pricingrules] = plan.pricing_rules.map do |pr|
|
12
|
-
pr.
|
12
|
+
pr.merge('metric' => metric_info(pr, 'PricingRule'),
|
13
|
+
'cost_per_unit' => pr.fetch('cost_per_unit').to_f)
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
@@ -54,8 +54,6 @@ module ThreeScaleToolbox
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def metric_info(elem, elem_name)
|
57
|
-
# Methods are included in metrics.
|
58
|
-
# First methods must be checked, otherwise it could be considered as a false metric
|
59
57
|
if (method = find_method(elem.fetch('metric_id')))
|
60
58
|
{ 'type' => 'method', 'system_name' => method.fetch('system_name') }
|
61
59
|
elsif (metric = find_metric(elem.fetch('metric_id')))
|
@@ -9,10 +9,11 @@ module ThreeScaleToolbox
|
|
9
9
|
def call
|
10
10
|
plan_obj = Entities::ApplicationPlan.find(service: service, ref: plan_system_name)
|
11
11
|
if plan_obj.nil?
|
12
|
-
plan_obj = Entities::ApplicationPlan.create(service: service,
|
12
|
+
plan_obj = Entities::ApplicationPlan.create(service: service,
|
13
|
+
plan_attrs: create_plan_attrs)
|
13
14
|
puts "Application plan created: #{plan_obj.id}"
|
14
15
|
else
|
15
|
-
res = plan_obj.update(
|
16
|
+
res = plan_obj.update(update_plan_attrs)
|
16
17
|
if (errors = res['errors'])
|
17
18
|
raise ThreeScaleToolbox::Error, "Could not update application plan #{plan_system_name}. Errors: #{errors}"
|
18
19
|
end
|
@@ -23,9 +24,13 @@ module ThreeScaleToolbox
|
|
23
24
|
|
24
25
|
private
|
25
26
|
|
26
|
-
def
|
27
|
+
def create_plan_attrs
|
27
28
|
resource_plan.merge('system_name' => plan_system_name)
|
28
29
|
end
|
30
|
+
|
31
|
+
def update_plan_attrs
|
32
|
+
resource_plan.reject { |key, _| %w[system_name].include? key }
|
33
|
+
end
|
29
34
|
end
|
30
35
|
end
|
31
36
|
end
|
@@ -18,9 +18,6 @@ module ThreeScaleToolbox
|
|
18
18
|
private
|
19
19
|
|
20
20
|
def missing_metrics
|
21
|
-
# service metrics list includes methods
|
22
|
-
# this array_difference method computes elements in resource_metrics not included in service_metrics
|
23
|
-
# So methods will not be in the "missing_metrics" list, as long as array diff semantics are kept.
|
24
21
|
ThreeScaleToolbox::Helper.array_difference(resource_metrics, service_metrics) do |a, b|
|
25
22
|
ThreeScaleToolbox::Helper.compare_hashes(a, b, ['system_name'])
|
26
23
|
end
|
@@ -21,15 +21,22 @@ module ThreeScaleToolbox
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def missing_pricing_rules
|
24
|
-
ThreeScaleToolbox::Helper.array_difference(resource_pr_processed,
|
24
|
+
ThreeScaleToolbox::Helper.array_difference(resource_pr_processed, remote_pr_processed) do |a, b|
|
25
25
|
ThreeScaleToolbox::Helper.compare_hashes(a, b, %w[metric_id cost_per_unit min max])
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
def remote_pr_processed
|
30
|
+
plan.pricing_rules.map do |pr|
|
31
|
+
pr.merge('cost_per_unit' => pr.fetch('cost_per_unit').to_f)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
29
35
|
def resource_pr_processed
|
30
36
|
resource_pricing_rules.map do |pr|
|
31
37
|
metric = find_metric_by_system_name(pr.delete('metric_system_name'))
|
32
|
-
pr.merge('metric_id' => metric.fetch('id')
|
38
|
+
pr.merge('metric_id' => metric.fetch('id'),
|
39
|
+
'cost_per_unit' => pr.fetch('cost_per_unit').to_f)
|
33
40
|
end
|
34
41
|
end
|
35
42
|
end
|
@@ -81,6 +81,10 @@ module ThreeScaleToolbox
|
|
81
81
|
context[:service_methods] ||= service.methods(service_hits['id'])
|
82
82
|
end
|
83
83
|
|
84
|
+
def service_metrics_and_methods
|
85
|
+
service_metrics + service_methods
|
86
|
+
end
|
87
|
+
|
84
88
|
def invalidate_service_methods
|
85
89
|
context[:service_methods] = nil
|
86
90
|
end
|
@@ -99,7 +103,7 @@ module ThreeScaleToolbox
|
|
99
103
|
end
|
100
104
|
|
101
105
|
def find_metric_by_system_name(system_name)
|
102
|
-
|
106
|
+
service_metrics_and_methods.find { |metric| metric['system_name'] == system_name }
|
103
107
|
end
|
104
108
|
|
105
109
|
private
|
@@ -19,8 +19,12 @@ module ThreeScaleToolbox
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def run
|
22
|
-
|
23
|
-
|
22
|
+
if promotable?
|
23
|
+
latest_proxy_config_from.promote(to: to_env)
|
24
|
+
puts "Proxy Configuration version #{latest_proxy_config_from.version} promoted to '#{to_env}'"
|
25
|
+
else
|
26
|
+
warn "warning: Nothing to promote. Proxy Configuration version #{latest_proxy_config_from.version} already promoted to production"
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
private
|
@@ -29,16 +33,28 @@ module ThreeScaleToolbox
|
|
29
33
|
@remote ||= threescale_client(arguments[:remote])
|
30
34
|
end
|
31
35
|
|
32
|
-
def
|
33
|
-
@
|
36
|
+
def latest_proxy_config_from
|
37
|
+
@proxy_config_from ||= find_proxy_config_latest_from
|
38
|
+
end
|
39
|
+
|
40
|
+
def latest_proxy_config_to
|
41
|
+
@proxy_config_to ||= find_proxy_config_latest_to
|
34
42
|
end
|
35
43
|
|
36
|
-
def
|
44
|
+
def promotable?
|
45
|
+
return latest_proxy_config_to.nil? || latest_proxy_config_from.version != latest_proxy_config_to.version
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_proxy_config_latest_from
|
37
49
|
Entities::ProxyConfig.find_latest(service: service, environment: from_env).tap do |pc|
|
38
50
|
raise ThreeScaleToolbox::Error, "ProxyConfig #{from_env} in service #{service.id} does not exist" if pc.nil?
|
39
51
|
end
|
40
52
|
end
|
41
53
|
|
54
|
+
def find_proxy_config_latest_to
|
55
|
+
Entities::ProxyConfig.find_latest(service: service, environment: to_env)
|
56
|
+
end
|
57
|
+
|
42
58
|
def service_ref
|
43
59
|
arguments[:service_ref]
|
44
60
|
end
|
@@ -20,15 +20,55 @@ module ThreeScaleToolbox
|
|
20
20
|
find_by_text(ref, remote)
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
# ref can be
|
24
|
+
# * Email of the account user.
|
25
|
+
# * Username of the account user.
|
26
|
+
# * ID of the account user.
|
27
|
+
# * [Master API] Provider key of the account
|
28
|
+
# * [Master API] Service token of the account service.
|
29
|
+
#
|
30
|
+
# email, username or user_id fields search with AND logic. Therefore separate requests.
|
31
|
+
# buyer_provider_key, buyer_service_token fields search with OR logic. Same request.
|
32
|
+
def find_by_text(ref, remote)
|
33
|
+
account = find_by_email(remote, ref)
|
34
|
+
return account unless account.nil?
|
35
|
+
|
36
|
+
account = find_by_username(remote, ref)
|
37
|
+
return account unless account.nil?
|
38
|
+
|
39
|
+
account = find_by_user_id(remote, ref)
|
40
|
+
return account unless account.nil?
|
41
|
+
|
42
|
+
account = find_by_provider_or_service_token(remote, ref)
|
43
|
+
return account unless account.nil?
|
44
|
+
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_by_email(remote, email)
|
49
|
+
generic_find(remote, email: email)
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_by_username(remote, username)
|
53
|
+
generic_find(remote, username: username)
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_by_user_id(remote, user_id)
|
57
|
+
generic_find(remote, user_id: user_id)
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_by_provider_or_service_token(remote, text)
|
61
|
+
generic_find(remote, buyer_provider_key: text, buyer_service_token: text)
|
62
|
+
end
|
63
|
+
|
64
|
+
def generic_find(remote, criteria)
|
65
|
+
account = remote.find_account(criteria)
|
26
66
|
if (errors = account['errors'])
|
27
67
|
raise ThreeScaleToolbox::ThreeScaleApiError.new(
|
28
68
|
'Account find returned errors', errors
|
29
69
|
)
|
30
70
|
end
|
31
|
-
new(id: account['id'], remote:
|
71
|
+
new(id: account['id'], remote: remote, attrs: account)
|
32
72
|
rescue ThreeScale::API::HttpClient::NotFoundError
|
33
73
|
nil
|
34
74
|
end
|