3scale_toolbox 0.8.0 → 0.9.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -1
  3. data/lib/3scale_toolbox/cli/error_handler.rb +0 -2
  4. data/lib/3scale_toolbox/commands/3scale_command.rb +0 -4
  5. data/lib/3scale_toolbox/commands/copy_command/copy_service.rb +5 -4
  6. data/lib/3scale_toolbox/commands/copy_command.rb +0 -2
  7. data/lib/3scale_toolbox/commands/help_command.rb +0 -3
  8. data/lib/3scale_toolbox/commands/import_command/import_csv.rb +0 -6
  9. data/lib/3scale_toolbox/commands/import_command/openapi/create_activedocs_step.rb +39 -2
  10. data/lib/3scale_toolbox/commands/import_command/openapi/create_method_step.rb +1 -1
  11. data/lib/3scale_toolbox/commands/import_command/openapi/create_service_step.rb +5 -16
  12. data/lib/3scale_toolbox/commands/import_command/openapi/mapping_rule.rb +11 -1
  13. data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +4 -3
  14. data/lib/3scale_toolbox/commands/import_command/openapi/threescale_api_spec.rb +13 -2
  15. data/lib/3scale_toolbox/commands/import_command/openapi/update_policies_step.rb +63 -14
  16. data/lib/3scale_toolbox/commands/import_command/openapi/update_service_proxy_step.rb +6 -3
  17. data/lib/3scale_toolbox/commands/import_command/openapi.rb +11 -5
  18. data/lib/3scale_toolbox/commands/import_command.rb +0 -2
  19. data/lib/3scale_toolbox/commands/plans_command/apply_command.rb +136 -0
  20. data/lib/3scale_toolbox/commands/plans_command/create_command.rb +100 -0
  21. data/lib/3scale_toolbox/commands/plans_command/delete_command.rb +66 -0
  22. data/lib/3scale_toolbox/commands/plans_command/export/read_app_plan_step.rb +16 -0
  23. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_features_step.rb +16 -0
  24. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_limits_step.rb +19 -0
  25. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_methods_step.rb +50 -0
  26. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_metrics_step.rb +49 -0
  27. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step.rb +19 -0
  28. data/lib/3scale_toolbox/commands/plans_command/export/step.rb +95 -0
  29. data/lib/3scale_toolbox/commands/plans_command/export/write_artifacts_file_step.rb +84 -0
  30. data/lib/3scale_toolbox/commands/plans_command/export_command.rb +65 -0
  31. data/lib/3scale_toolbox/commands/plans_command/import/create_or_update_app_plan_step.rb +33 -0
  32. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_features_step.rb +45 -0
  33. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_limits_step.rb +41 -0
  34. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_metrics_step.rb +57 -0
  35. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +39 -0
  36. data/lib/3scale_toolbox/commands/plans_command/import/step.rb +129 -0
  37. data/lib/3scale_toolbox/commands/plans_command/import_command.rb +62 -0
  38. data/lib/3scale_toolbox/commands/plans_command/list_command.rb +63 -0
  39. data/lib/3scale_toolbox/commands/plans_command/show_command.rb +81 -0
  40. data/lib/3scale_toolbox/commands/plans_command.rb +34 -0
  41. data/lib/3scale_toolbox/commands/remote_command.rb +0 -3
  42. data/lib/3scale_toolbox/commands/update_command/update_service.rb +5 -4
  43. data/lib/3scale_toolbox/commands/update_command.rb +0 -2
  44. data/lib/3scale_toolbox/commands.rb +3 -1
  45. data/lib/3scale_toolbox/entities/application_plan.rb +150 -0
  46. data/lib/3scale_toolbox/entities/service.rb +25 -12
  47. data/lib/3scale_toolbox/entities.rb +1 -0
  48. data/lib/3scale_toolbox/helper.rb +41 -0
  49. data/lib/3scale_toolbox/resource_reader.rb +42 -0
  50. data/lib/3scale_toolbox/tasks/copy_app_plans_task.rb +1 -1
  51. data/lib/3scale_toolbox/tasks/copy_limits_task.rb +8 -11
  52. data/lib/3scale_toolbox/tasks/copy_pricingrules_task.rb +5 -3
  53. data/lib/3scale_toolbox/version.rb +1 -1
  54. data/lib/3scale_toolbox.rb +10 -0
  55. metadata +28 -5
  56. data/lib/3scale_toolbox/commands/import_command/openapi/resource_reader.rb +0 -51
@@ -0,0 +1,41 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module Import
5
+ class ImportMetricLimitsStep
6
+ include Step
7
+ ##
8
+ # Writes Plan limits
9
+ def call
10
+ missing_limits.each do |limit|
11
+ metric_id = limit.delete('metric_id')
12
+ limit_obj = plan.create_limit(metric_id, limit)
13
+ if (errors = limit_obj['errors'])
14
+ raise ThreeScaleToolbox::Error, "Plan limit has not been created. #{errors}"
15
+ end
16
+
17
+ puts "Created plan limit: [metric: #{metric_id}, #{limit}]"
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def missing_limits
24
+ ThreeScaleToolbox::Helper.array_difference(resource_limits_processed, plan.limits) do |a, b|
25
+ ThreeScaleToolbox::Helper.compare_hashes(a, b, %w[metric_id period])
26
+ end
27
+ end
28
+
29
+ def resource_limits_processed
30
+ resource_limits.map do |limit|
31
+ metric = find_metric_by_system_name(limit.delete('metric_system_name'))
32
+ # this ImportMetricLimitsStep step is assuming all metrics/methods have been created
33
+ # in previous step, so finding metric should always succeed.
34
+ limit.merge('metric_id' => metric.fetch('id'))
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,57 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module Import
5
+ class ImportMetricsStep
6
+ include Step
7
+ ##
8
+ # Writes Plan metrics and methods
9
+ def call
10
+ missing_metrics.each(&method(:create_metric))
11
+ missing_methods.each(&method(:create_method))
12
+
13
+ # invalidate memoized methods and metrics
14
+ invalidate_service_methods
15
+ invalidate_service_metrics
16
+ end
17
+
18
+ private
19
+
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
+ ThreeScaleToolbox::Helper.array_difference(resource_metrics, service_metrics) do |a, b|
25
+ ThreeScaleToolbox::Helper.compare_hashes(a, b, ['system_name'])
26
+ end
27
+ end
28
+
29
+ def missing_methods
30
+ ThreeScaleToolbox::Helper.array_difference(resource_methods, service_methods) do |a, b|
31
+ ThreeScaleToolbox::Helper.compare_hashes(a, b, ['system_name'])
32
+ end
33
+ end
34
+
35
+ def create_metric(metric_attrs)
36
+ metric = service.create_metric(metric_attrs)
37
+ if (errors = metric['errors'])
38
+ raise ThreeScaleToolbox::Error, "Metric has not been created. #{errors}"
39
+ end
40
+
41
+ puts "Created metric: #{metric['system_name']}"
42
+ end
43
+
44
+ def create_method(method_attrs)
45
+ method = service.create_method(service_hits['id'], method_attrs)
46
+ if (errors = method['errors'])
47
+ raise ThreeScaleToolbox::Error, "Method has not been created. #{errors}" \
48
+
49
+ end
50
+
51
+ puts "Created method: #{method_attrs['system_name']}"
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,39 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module Import
5
+ class ImportPricingRulesStep
6
+ include Step
7
+ ##
8
+ # Writes Plan pricing rules
9
+ def call
10
+ missing_pricing_rules.each do |pr|
11
+ metric_id = pr.delete('metric_id')
12
+ resp = plan.create_pricing_rule(metric_id, pr)
13
+ if (errors = resp['errors'])
14
+ raise ThreeScaleToolbox::Error, "Plan pricing rule has not been created. #{errors}"
15
+ end
16
+
17
+ puts "Created plan pricing rule: [metric: #{metric_id}, #{pr}]"
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def missing_pricing_rules
24
+ ThreeScaleToolbox::Helper.array_difference(resource_pr_processed, plan.pricing_rules) do |a, b|
25
+ ThreeScaleToolbox::Helper.compare_hashes(a, b, %w[metric_id cost_per_unit min max])
26
+ end
27
+ end
28
+
29
+ def resource_pr_processed
30
+ resource_pricing_rules.map do |pr|
31
+ metric = find_metric_by_system_name(pr.delete('metric_system_name'))
32
+ pr.merge('metric_id' => metric.fetch('id'))
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,129 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module Import
5
+ module Step
6
+ attr_reader :context
7
+
8
+ def initialize(context)
9
+ @context = context
10
+ end
11
+
12
+ def service
13
+ context[:service] ||= find_service
14
+ end
15
+
16
+ def file
17
+ context[:file]
18
+ end
19
+
20
+ def threescale_client
21
+ context[:threescale_client]
22
+ end
23
+
24
+ # can be id or system_name
25
+ def service_system_name
26
+ context[:service_system_name]
27
+ end
28
+
29
+ # can be id or system_name
30
+ def plan_system_name
31
+ context[:plan_system_name] || artifacts_resource.dig('plan', 'system_name')
32
+ end
33
+
34
+ def result
35
+ context[:result] ||= {}
36
+ end
37
+
38
+ def plan
39
+ context[:plan] ||= find_plan
40
+ end
41
+
42
+ def resource_plan
43
+ artifacts_resource.fetch('plan') do
44
+ raise ThreeScaleToolbox::Error, 'Invalid content. Plan not found'
45
+ end
46
+ end
47
+
48
+ def resource_metrics
49
+ artifacts_resource['metrics'] || []
50
+ end
51
+
52
+ def resource_methods
53
+ artifacts_resource['methods'] || []
54
+ end
55
+
56
+ def resource_limits
57
+ artifacts_resource['limits'] || []
58
+ end
59
+
60
+ def resource_pricing_rules
61
+ artifacts_resource['pricingrules'] || []
62
+ end
63
+
64
+ def resource_features
65
+ artifacts_resource['plan_features'] || []
66
+ end
67
+
68
+ def service_metrics
69
+ context[:service_metrics] ||= service.metrics
70
+ end
71
+
72
+ def invalidate_service_metrics
73
+ context[:service_metrics] = nil
74
+ end
75
+
76
+ def service_hits
77
+ context[:service_hits] ||= find_service_hits
78
+ end
79
+
80
+ def service_methods
81
+ context[:service_methods] ||= service.methods
82
+ end
83
+
84
+ def invalidate_service_methods
85
+ context[:service_methods] = nil
86
+ end
87
+
88
+ def service_features
89
+ context[:service_features] ||= service.features
90
+ end
91
+
92
+ # deserialized artifacts content
93
+ def artifacts_resource
94
+ context[:artifacts_resource]
95
+ end
96
+
97
+ def find_feature_by_system_name(system_name)
98
+ service_features.find { |feature| feature['system_name'] == system_name }
99
+ end
100
+
101
+ def find_metric_by_system_name(system_name)
102
+ service_metrics.find { |metric| metric['system_name'] == system_name }
103
+ end
104
+
105
+ private
106
+
107
+ def find_service
108
+ Entities::Service.find(remote: threescale_client,
109
+ ref: service_system_name).tap do |svc|
110
+ raise ThreeScaleToolbox::Error, "Service #{service_system_name} does not exist" if svc.nil?
111
+ end
112
+ end
113
+
114
+ def find_plan
115
+ Entities::ApplicationPlan.find(service: service, ref: plan_system_name).tap do |p|
116
+ raise ThreeScaleToolbox::Error, "Application plan #{plan_system_name} does not exist" if p.nil?
117
+ end
118
+ end
119
+
120
+ def find_service_hits
121
+ find_metric_by_system_name('hits').tap do |hits_metric|
122
+ raise ThreeScaleToolbox::Error, 'missing hits metric' if hits_metric.nil?
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,62 @@
1
+ require '3scale_toolbox/commands/plans_command/import/step'
2
+ require '3scale_toolbox/commands/plans_command/import/create_or_update_app_plan_step'
3
+ require '3scale_toolbox/commands/plans_command/import/import_plan_features_step'
4
+ require '3scale_toolbox/commands/plans_command/import/import_plan_metrics_step'
5
+ require '3scale_toolbox/commands/plans_command/import/import_plan_limits_step'
6
+ require '3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step'
7
+
8
+ module ThreeScaleToolbox
9
+ module Commands
10
+ module PlansCommand
11
+ module Import
12
+ class ImportSubcommand < Cri::CommandRunner
13
+ include ThreeScaleToolbox::Command
14
+ include ThreeScaleToolbox::ResourceReader
15
+
16
+ def self.command
17
+ Cri::Command.define do
18
+ name 'import'
19
+ usage 'import [opts] <remote> <service_system_name>'
20
+ summary 'import application plan'
21
+ description 'Import application plan, limits, pricing rules and features'
22
+
23
+ option :f, :file, 'Read from file or url instead of stdin', argument: :required
24
+ option :p, :plan, 'Override application plan reference', argument: :required
25
+ param :remote
26
+ param :service_system_name
27
+
28
+ runner ImportSubcommand
29
+ end
30
+ end
31
+
32
+ def run
33
+ tasks = []
34
+ tasks << CreateOrUpdateAppPlanStep.new(context)
35
+ tasks << ImportMetricsStep.new(context)
36
+ tasks << ImportMetricLimitsStep.new(context)
37
+ tasks << ImportPricingRulesStep.new(context)
38
+ tasks << ImportPlanFeaturesStep.new(context)
39
+
40
+ # run tasks
41
+ tasks.each(&:call)
42
+ end
43
+
44
+ private
45
+
46
+ def context
47
+ @context ||= create_context
48
+ end
49
+
50
+ def create_context
51
+ {
52
+ artifacts_resource: load_resource(options[:file] || '-'),
53
+ threescale_client: threescale_client(arguments[:remote]),
54
+ service_system_name: arguments[:service_system_name],
55
+ plan_system_name: options[:plan],
56
+ }
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,63 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module List
5
+ class ListSubcommand < Cri::CommandRunner
6
+ include ThreeScaleToolbox::Command
7
+
8
+ FIELDS_TO_SHOW = %w[id name system_name].freeze
9
+
10
+ def self.command
11
+ Cri::Command.define do
12
+ name 'list'
13
+ usage 'list [opts] <remote> <service>'
14
+ summary 'list application plans'
15
+ description 'List application plans'
16
+
17
+ param :remote
18
+ param :service_ref
19
+
20
+ runner ListSubcommand
21
+ end
22
+ end
23
+
24
+ def run
25
+ print_header
26
+ print_data
27
+ end
28
+
29
+ private
30
+
31
+ def print_header
32
+ puts FIELDS_TO_SHOW.map(&:upcase).join("\t")
33
+ end
34
+
35
+ def print_data
36
+ service.plans.each do |plan|
37
+ puts FIELDS_TO_SHOW.map { |field| plan.fetch(field, '(empty)') }.join("\t")
38
+ end
39
+ end
40
+
41
+ def service
42
+ @service ||= find_service
43
+ end
44
+
45
+ def find_service
46
+ Entities::Service.find(remote: remote,
47
+ ref: service_ref).tap do |svc|
48
+ raise ThreeScaleToolbox::Error, "Service #{service_ref} does not exist" if svc.nil?
49
+ end
50
+ end
51
+
52
+ def remote
53
+ @remote ||= threescale_client(arguments[:remote])
54
+ end
55
+
56
+ def service_ref
57
+ arguments[:service_ref]
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,81 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module Show
5
+ class ShowSubcommand < Cri::CommandRunner
6
+ include ThreeScaleToolbox::Command
7
+
8
+ FIELDS_TO_SHOW = %w[id name system_name approval_required end_user_required
9
+ cost_per_month setup_fee trial_period_days].freeze
10
+
11
+ def self.command
12
+ Cri::Command.define do
13
+ name 'show'
14
+ usage 'show [opts] <remote> <service> <plan>'
15
+ summary 'show application plan'
16
+ description 'show application plan'
17
+
18
+ param :remote
19
+ param :service_ref
20
+ param :plan_ref
21
+
22
+ runner ShowSubcommand
23
+ end
24
+ end
25
+
26
+ def run
27
+ print_header
28
+ print_data
29
+ end
30
+
31
+ private
32
+
33
+ def print_header
34
+ puts FIELDS_TO_SHOW.map(&:upcase).join("\t")
35
+ end
36
+
37
+ def print_data
38
+ puts FIELDS_TO_SHOW.map { |field| plan_attrs.fetch(field, '(empty)') }.join("\t")
39
+ end
40
+
41
+ def service
42
+ @service ||= find_service
43
+ end
44
+
45
+ def plan_attrs
46
+ @plan_attrs ||= plan.show
47
+ end
48
+
49
+ def plan
50
+ @plan ||= find_plan
51
+ end
52
+
53
+ def find_service
54
+ Entities::Service.find(remote: remote,
55
+ ref: service_ref).tap do |svc|
56
+ raise ThreeScaleToolbox::Error, "Service #{service_ref} does not exist" if svc.nil?
57
+ end
58
+ end
59
+
60
+ def find_plan
61
+ Entities::ApplicationPlan.find(service: service, ref: plan_ref).tap do |p|
62
+ raise ThreeScaleToolbox::Error, "Application plan #{plan_ref} does not exist" if p.nil?
63
+ end
64
+ end
65
+
66
+ def remote
67
+ @remote ||= threescale_client(arguments[:remote])
68
+ end
69
+
70
+ def service_ref
71
+ arguments[:service_ref]
72
+ end
73
+
74
+ def plan_ref
75
+ arguments[:plan_ref]
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,34 @@
1
+ require '3scale_toolbox/commands/plans_command/export_command'
2
+ require '3scale_toolbox/commands/plans_command/import_command'
3
+ require '3scale_toolbox/commands/plans_command/create_command'
4
+ require '3scale_toolbox/commands/plans_command/apply_command'
5
+ require '3scale_toolbox/commands/plans_command/list_command'
6
+ require '3scale_toolbox/commands/plans_command/show_command'
7
+ require '3scale_toolbox/commands/plans_command/delete_command'
8
+
9
+ module ThreeScaleToolbox
10
+ module Commands
11
+ module PlansCommand
12
+ include ThreeScaleToolbox::Command
13
+ def self.command
14
+ Cri::Command.define do
15
+ name 'application-plan'
16
+ usage 'application-plan <sub-command> [options]'
17
+ summary 'application-plan super command'
18
+ description 'Application plan commands'
19
+
20
+ run do |_opts, _args, cmd|
21
+ puts cmd.help
22
+ end
23
+ end
24
+ end
25
+ add_subcommand(Export::ExportSubcommand)
26
+ add_subcommand(Import::ImportSubcommand)
27
+ add_subcommand(Create::CreateSubcommand)
28
+ add_subcommand(Apply::ApplySubcommand)
29
+ add_subcommand(List::ListSubcommand)
30
+ add_subcommand(Show::ShowSubcommand)
31
+ add_subcommand(Delete::DeleteSubcommand)
32
+ end
33
+ end
34
+ end
@@ -1,6 +1,3 @@
1
- require 'cri'
2
- require '3scale_toolbox/base_command'
3
- require '3scale_toolbox/remotes'
4
1
  require '3scale_toolbox/commands/remote_command/remote_add'
5
2
  require '3scale_toolbox/commands/remote_command/remote_remove'
6
3
  require '3scale_toolbox/commands/remote_command/remote_rename'
@@ -1,6 +1,3 @@
1
- require 'cri'
2
- require '3scale_toolbox/base_command'
3
-
4
1
  module ThreeScaleToolbox
5
2
  module Commands
6
3
  module UpdateCommand
@@ -41,7 +38,6 @@ module ThreeScaleToolbox
41
38
  tasks = []
42
39
  unless options[:'rules-only']
43
40
  tasks << Tasks::UpdateServiceSettingsTask.new(context.merge(target_name: system_name))
44
- tasks << Tasks::CopyServiceProxyTask.new(context)
45
41
  tasks << Tasks::CopyMethodsTask.new(context)
46
42
  tasks << Tasks::CopyMetricsTask.new(context)
47
43
  tasks << Tasks::CopyApplicationPlansTask.new(context)
@@ -50,6 +46,11 @@ module ThreeScaleToolbox
50
46
  tasks << Tasks::CopyPricingRulesTask.new(context)
51
47
  tasks << Tasks::DeleteActiveDocsTask.new(context)
52
48
  tasks << Tasks::CopyActiveDocsTask.new(context)
49
+ # Copy proxy must be the last task
50
+ # Proxy update is the mechanism to increase version of the proxy,
51
+ # Hence propagating (mapping rules, poicies, oidc, auth) update to
52
+ # latest proxy config, making available to gateway.
53
+ tasks << Tasks::CopyServiceProxyTask.new(context)
53
54
  end
54
55
  tasks << Tasks::DestroyMappingRulesTask.new(context) if options[:force]
55
56
  tasks << Tasks::CopyMappingRulesTask.new(context)
@@ -1,5 +1,3 @@
1
- require 'cri'
2
- require '3scale_toolbox/base_command'
3
1
  require '3scale_toolbox/commands/update_command/update_service'
4
2
 
5
3
  module ThreeScaleToolbox
@@ -4,6 +4,7 @@ require '3scale_toolbox/commands/copy_command'
4
4
  require '3scale_toolbox/commands/import_command'
5
5
  require '3scale_toolbox/commands/update_command'
6
6
  require '3scale_toolbox/commands/remote_command'
7
+ require '3scale_toolbox/commands/plans_command'
7
8
 
8
9
  module ThreeScaleToolbox
9
10
  module Commands
@@ -12,7 +13,8 @@ module ThreeScaleToolbox
12
13
  ThreeScaleToolbox::Commands::CopyCommand,
13
14
  ThreeScaleToolbox::Commands::ImportCommand,
14
15
  ThreeScaleToolbox::Commands::UpdateCommand,
15
- ThreeScaleToolbox::Commands::RemoteCommand::RemoteCommand
16
+ ThreeScaleToolbox::Commands::RemoteCommand::RemoteCommand,
17
+ ThreeScaleToolbox::Commands::PlansCommand,
16
18
  ].freeze
17
19
  end
18
20
  end