3scale_toolbox 0.12.4 → 0.17.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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/3scale_toolbox.gemspec +4 -3
  3. data/README.md +31 -10
  4. data/lib/3scale_toolbox.rb +5 -2
  5. data/lib/3scale_toolbox/attribute_filters.rb +2 -0
  6. data/lib/3scale_toolbox/attribute_filters/attribute_filter.rb +9 -0
  7. data/lib/3scale_toolbox/attribute_filters/service_id_from_ref_filter.rb +30 -0
  8. data/lib/3scale_toolbox/cli.rb +4 -0
  9. data/lib/3scale_toolbox/cli/custom_table_printer.rb +32 -0
  10. data/lib/3scale_toolbox/cli/error_handler.rb +17 -14
  11. data/lib/3scale_toolbox/cli/json_printer.rb +13 -0
  12. data/lib/3scale_toolbox/cli/output_flag.rb +20 -0
  13. data/lib/3scale_toolbox/cli/yaml_printer.rb +13 -0
  14. data/lib/3scale_toolbox/commands.rb +5 -1
  15. data/lib/3scale_toolbox/commands/activedocs_command/apply_command.rb +34 -11
  16. data/lib/3scale_toolbox/commands/activedocs_command/create_command.rb +22 -7
  17. data/lib/3scale_toolbox/commands/activedocs_command/list_command.rb +21 -11
  18. data/lib/3scale_toolbox/commands/application_command/apply_command.rb +27 -4
  19. data/lib/3scale_toolbox/commands/application_command/create_command.rb +16 -1
  20. data/lib/3scale_toolbox/commands/application_command/list_command.rb +10 -13
  21. data/lib/3scale_toolbox/commands/application_command/show_command.rb +8 -14
  22. data/lib/3scale_toolbox/commands/backend_command.rb +22 -0
  23. data/lib/3scale_toolbox/commands/backend_command/copy_command.rb +65 -0
  24. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_mapping_rules_task.rb +52 -0
  25. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_methods_task.rb +40 -0
  26. data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_metrics_task.rb +30 -0
  27. data/lib/3scale_toolbox/commands/backend_command/copy_command/create_or_update_target_backend_task.rb +45 -0
  28. data/lib/3scale_toolbox/commands/backend_command/copy_command/task.rb +89 -0
  29. data/lib/3scale_toolbox/commands/copy_command.rb +2 -2
  30. data/lib/3scale_toolbox/commands/copy_command/service_command.rb +40 -0
  31. data/lib/3scale_toolbox/commands/import_command/openapi.rb +29 -7
  32. data/lib/3scale_toolbox/commands/import_command/openapi/create_activedocs_step.rb +4 -17
  33. data/lib/3scale_toolbox/commands/import_command/openapi/create_service_step.rb +1 -5
  34. data/lib/3scale_toolbox/commands/import_command/openapi/mapping_rule.rb +3 -2
  35. data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +43 -5
  36. data/lib/3scale_toolbox/commands/import_command/openapi/update_policies_step.rb +9 -10
  37. data/lib/3scale_toolbox/commands/import_command/openapi/update_service_oidc_conf_step.rb +2 -17
  38. data/lib/3scale_toolbox/commands/import_command/openapi/update_service_proxy_step.rb +10 -10
  39. data/lib/3scale_toolbox/commands/methods_command/apply_command.rb +26 -4
  40. data/lib/3scale_toolbox/commands/methods_command/create_command.rb +23 -1
  41. data/lib/3scale_toolbox/commands/methods_command/list_command.rb +11 -9
  42. data/lib/3scale_toolbox/commands/metrics_command/apply_command.rb +26 -4
  43. data/lib/3scale_toolbox/commands/metrics_command/create_command.rb +23 -1
  44. data/lib/3scale_toolbox/commands/metrics_command/list_command.rb +7 -12
  45. data/lib/3scale_toolbox/commands/plans_command/apply_command.rb +36 -7
  46. data/lib/3scale_toolbox/commands/plans_command/create_command.rb +23 -1
  47. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_limits_step.rb +11 -12
  48. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +11 -12
  49. data/lib/3scale_toolbox/commands/plans_command/list_command.rb +8 -13
  50. data/lib/3scale_toolbox/commands/plans_command/show_command.rb +6 -14
  51. data/lib/3scale_toolbox/commands/product_command.rb +22 -0
  52. data/lib/3scale_toolbox/commands/product_command/copy_command.rb +78 -0
  53. data/lib/3scale_toolbox/commands/product_command/copy_command/copy_backends_task.rb +71 -0
  54. data/lib/3scale_toolbox/commands/product_command/copy_command/delete_target_backend_usages_task.rb +48 -0
  55. data/lib/3scale_toolbox/commands/proxy_config_command.rb +3 -0
  56. data/lib/3scale_toolbox/commands/proxy_config_command/export_command.rb +74 -0
  57. data/lib/3scale_toolbox/commands/proxy_config_command/helper.rb +15 -0
  58. data/lib/3scale_toolbox/commands/proxy_config_command/list_command.rb +13 -29
  59. data/lib/3scale_toolbox/commands/proxy_config_command/show_command.rb +20 -23
  60. data/lib/3scale_toolbox/commands/service_command.rb +7 -5
  61. data/lib/3scale_toolbox/commands/service_command/apply_command.rb +69 -58
  62. data/lib/3scale_toolbox/commands/service_command/copy_command.rb +95 -0
  63. data/lib/3scale_toolbox/commands/service_command/copy_command/bump_proxy_version_task.rb +36 -0
  64. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_activedocs_task.rb +46 -0
  65. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_app_plans_task.rb +35 -0
  66. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_limits_task.rb +39 -0
  67. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_mapping_rules_task.rb +35 -0
  68. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_methods_task.rb +40 -0
  69. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_metrics_task.rb +37 -0
  70. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_policies_task.rb +17 -0
  71. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_pricingrules_task.rb +44 -0
  72. data/lib/3scale_toolbox/commands/service_command/copy_command/copy_service_proxy_task.rb +32 -0
  73. data/lib/3scale_toolbox/commands/service_command/copy_command/create_or_update_service_task.rb +48 -0
  74. data/lib/3scale_toolbox/commands/service_command/copy_command/destroy_mapping_rules_task.rb +34 -0
  75. data/lib/3scale_toolbox/commands/service_command/copy_command/task.rb +99 -0
  76. data/lib/3scale_toolbox/commands/service_command/create_command.rb +58 -44
  77. data/lib/3scale_toolbox/commands/service_command/delete_command.rb +31 -33
  78. data/lib/3scale_toolbox/commands/service_command/list_command.rb +24 -34
  79. data/lib/3scale_toolbox/commands/service_command/show_command.rb +39 -44
  80. data/lib/3scale_toolbox/commands/update_command.rb +3 -3
  81. data/lib/3scale_toolbox/commands/update_command/{update_service.rb → service_command.rb} +22 -18
  82. data/lib/3scale_toolbox/commands/update_command/service_command/copy_service_settings_task.rb +35 -0
  83. data/lib/3scale_toolbox/commands/update_command/service_command/delete_activedocs_task.rb +26 -0
  84. data/lib/3scale_toolbox/entities.rb +5 -0
  85. data/lib/3scale_toolbox/entities/application_plan.rb +31 -4
  86. data/lib/3scale_toolbox/entities/backend.rb +152 -0
  87. data/lib/3scale_toolbox/entities/backend_mapping_rule.rb +76 -0
  88. data/lib/3scale_toolbox/entities/backend_method.rb +90 -0
  89. data/lib/3scale_toolbox/entities/backend_metric.rb +88 -0
  90. data/lib/3scale_toolbox/entities/backend_usage.rb +99 -0
  91. data/lib/3scale_toolbox/entities/service.rb +18 -3
  92. data/lib/3scale_toolbox/error.rb +53 -0
  93. data/lib/3scale_toolbox/helper.rb +20 -0
  94. data/lib/3scale_toolbox/openapi.rb +2 -0
  95. data/lib/3scale_toolbox/openapi/oas3.rb +232 -0
  96. data/lib/3scale_toolbox/openapi/swagger.rb +192 -0
  97. data/lib/3scale_toolbox/proxy_logger.rb +1 -1
  98. data/lib/3scale_toolbox/version.rb +1 -1
  99. data/licenses.xml +190 -20
  100. data/resources/oas3_meta_schema.json +1654 -0
  101. metadata +69 -30
  102. data/lib/3scale_toolbox/commands/copy_command/copy_service.rb +0 -142
  103. data/lib/3scale_toolbox/commands/import_command/openapi/threescale_api_spec.rb +0 -80
  104. data/lib/3scale_toolbox/swagger.rb +0 -1
  105. data/lib/3scale_toolbox/swagger/swagger.rb +0 -123
  106. data/lib/3scale_toolbox/tasks.rb +0 -15
  107. data/lib/3scale_toolbox/tasks/bump_proxy_version_task.rb +0 -32
  108. data/lib/3scale_toolbox/tasks/copy_activedocs_task.rb +0 -42
  109. data/lib/3scale_toolbox/tasks/copy_app_plans_task.rb +0 -31
  110. data/lib/3scale_toolbox/tasks/copy_limits_task.rb +0 -36
  111. data/lib/3scale_toolbox/tasks/copy_mapping_rules_task.rb +0 -32
  112. data/lib/3scale_toolbox/tasks/copy_methods_task.rb +0 -36
  113. data/lib/3scale_toolbox/tasks/copy_metrics_task.rb +0 -33
  114. data/lib/3scale_toolbox/tasks/copy_policies_task.rb +0 -13
  115. data/lib/3scale_toolbox/tasks/copy_pricingrules_task.rb +0 -41
  116. data/lib/3scale_toolbox/tasks/copy_service_proxy_task.rb +0 -12
  117. data/lib/3scale_toolbox/tasks/copy_service_settings_task.rb +0 -38
  118. data/lib/3scale_toolbox/tasks/copy_task.rb +0 -66
  119. data/lib/3scale_toolbox/tasks/delete_activedocs_task.rb +0 -22
  120. data/lib/3scale_toolbox/tasks/destroy_mapping_rules_task.rb +0 -22
  121. data/lib/3scale_toolbox/tasks/helper_task.rb +0 -25
@@ -0,0 +1,48 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class CreateOrUpdateTargetServiceTask
6
+ include Task
7
+
8
+ def call
9
+ service = Entities::Service.find(remote: target_remote,
10
+ ref: target_service_ref)
11
+ if service == source
12
+ raise ThreeScaleToolbox::Error, 'Source and destination services are the same: ' \
13
+ "ID: #{source.id} system_name: #{source.attrs['system_name']}"
14
+ end
15
+
16
+ if service.nil?
17
+ service = Entities::Service.create(remote: target_remote,
18
+ service_params: create_attrs)
19
+ # Notify that mapping rules should be deleted before being copied
20
+ force_delete_mapping_rules
21
+ else
22
+ service.update update_attrs
23
+ end
24
+
25
+ # assign target service for other tasks to have it available
26
+ self.target = service
27
+
28
+ puts "new service id #{service.id}"
29
+ end
30
+
31
+ private
32
+
33
+ def target_service_ref
34
+ option_target_system_name || source.attrs.fetch('system_name')
35
+ end
36
+
37
+ def create_attrs
38
+ source.attrs.merge('system_name' => target_service_ref)
39
+ end
40
+
41
+ def update_attrs
42
+ source.attrs.merge('system_name' => target_service_ref)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,34 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ class DestroyMappingRulesTask
6
+ attr_reader :context
7
+
8
+ def initialize(context)
9
+ @context = context
10
+ end
11
+
12
+ def call
13
+ return unless delete_mapping_rules
14
+
15
+ puts 'destroying all mapping rules'
16
+ target.mapping_rules.each do |mapping_rule|
17
+ target.delete_mapping_rule mapping_rule['id']
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def delete_mapping_rules
24
+ context.fetch(:delete_mapping_rules, false)
25
+ end
26
+
27
+ def target
28
+ context[:target]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,99 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module ServiceCommand
4
+ module CopyCommand
5
+ module Task
6
+ attr_reader :context
7
+
8
+ def initialize(context)
9
+ @context = context
10
+ end
11
+
12
+ def source
13
+ context[:source] ||= find_source_service
14
+ end
15
+
16
+ def find_source_service
17
+ Entities::Service.find(remote: source_remote, ref: source_service_ref).tap do |svc|
18
+ raise ThreeScaleToolbox::Error, "Service #{source_service_ref} does not exist" if svc.nil?
19
+ end
20
+ end
21
+
22
+ def target
23
+ context[:target] ||= raise ThreeScaleToolbox::Error, 'Unexpected error. ' \
24
+ 'Target service should have been created or updated'
25
+ end
26
+
27
+ def target=(target)
28
+ context[:target] = target
29
+ end
30
+
31
+ def delete_mapping_rules
32
+ context.fetch(:delete_mapping_rules, false)
33
+ end
34
+
35
+ def force_delete_mapping_rules
36
+ context[:delete_mapping_rules] = true
37
+ end
38
+
39
+ def source_metrics
40
+ context[:source_metrics] ||= source.metrics
41
+ end
42
+
43
+ def source_hits
44
+ context[:source_hits] ||= source.hits
45
+ end
46
+
47
+ def source_methods
48
+ context[:source_methods] ||= source.methods(source_hits.fetch('id'))
49
+ end
50
+
51
+ def source_metrics_and_methods
52
+ source_metrics + source_methods
53
+ end
54
+
55
+ def target_metrics
56
+ context[:target_metrics] ||= target.metrics
57
+ end
58
+
59
+ def target_hits
60
+ context[:target_hits] ||= target.hits
61
+ end
62
+
63
+ def target_methods
64
+ context[:target_methods] ||= target.methods(target_hits.fetch('id'))
65
+ end
66
+
67
+ def target_metrics_and_methods
68
+ target_metrics + target_methods
69
+ end
70
+
71
+ def invalidate_target_methods
72
+ context[:target_methods] = nil
73
+ end
74
+
75
+ def invalidate_target_metrics
76
+ context[:target_metrics] = nil
77
+ end
78
+
79
+ def source_remote
80
+ context[:source_remote]
81
+ end
82
+
83
+ def target_remote
84
+ context[:target_remote]
85
+ end
86
+
87
+ def source_service_ref
88
+ context[:source_service_ref] ||= raise ThreeScaleToolbox::Error, 'Unexpected error. ' \
89
+ 'source_service_ref not found'
90
+ end
91
+
92
+ def option_target_system_name
93
+ context[:option_target_system_name]
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,58 +1,72 @@
1
1
  module ThreeScaleToolbox
2
2
  module Commands
3
3
  module ServiceCommand
4
- module Create
5
- class CreateSubcommand < Cri::CommandRunner
6
- include ThreeScaleToolbox::Command
7
-
8
- def self.command
9
- Cri::Command.define do
10
- name 'create'
11
- usage 'create [options] <remote> <service-name>'
12
- summary 'Create a service'
13
- description 'Create a service'
14
- runner CreateSubcommand
15
-
16
- param :remote
17
- param :service_name
18
-
19
- option :d, :'deployment-mode', "Specify the deployment mode of the service", argument: :required
20
- option :s, :'system-name', "Specify the system-name of the service", argument: :required
21
- option :a, :'authentication-mode', "Specify authentication mode of the service ('1' for API key, '2' for App Id / App Key, 'oauth' for OAuth mode, 'oidc' for OpenID Connect)", argument: :required
22
- option nil, :description, "Specify the description of the service", argument: :required
23
- option nil, :'support-email', "Specify the support email of the service", argument: :required
24
- end
25
- end
4
+ class CreateSubcommand < Cri::CommandRunner
5
+ include ThreeScaleToolbox::Command
6
+
7
+ class CustomPrinter
8
+ attr_reader :option_default, :option_disabled
26
9
 
27
- def run
28
- create_service_params = service_attrs
29
- result = Entities::Service.create(remote: remote, service_params: create_service_params)
30
- puts "Service '#{arguments[:service_name]}' has been created with ID: #{result.id}"
10
+ def print_record(service)
11
+ puts "Service '#{service['name']}' has been created with ID: #{service['id']}"
31
12
  end
32
13
 
33
- private
14
+ def print_collection(collection) end
15
+ end
34
16
 
35
- def remote
36
- @remote ||= threescale_client(arguments[:remote])
37
- end
17
+ def self.command
18
+ Cri::Command.define do
19
+ name 'create'
20
+ usage 'create [options] <remote> <service-name>'
21
+ summary 'Create a service'
22
+ description 'Create a service'
38
23
 
39
- def parse_options
40
- {
41
- "deployment_option" => options[:'deployment-mode'],
42
- "system_name" => options[:'system-name'],
43
- "backend_version" => options[:'authentication-mode'],
44
- "description" => options[:description],
45
- "support_email" => options[:'support-email'],
46
- }.compact
47
- end
24
+ param :remote
25
+ param :service_name
48
26
 
49
- def service_attrs
50
- service_name = arguments[:service_name]
51
- create_service_attrs = parse_options
52
- create_service_attrs["name"] = service_name
53
- create_service_attrs
27
+ ThreeScaleToolbox::CLI.output_flag(self)
28
+ option :d, :'deployment-mode', "Specify the deployment mode of the service", argument: :required
29
+ option :s, :'system-name', "Specify the system-name of the service", argument: :required
30
+ option :a, :'authentication-mode', "Specify authentication mode of the service ('1' for API key, '2' for App Id / App Key, 'oauth' for OAuth mode, 'oidc' for OpenID Connect)", argument: :required
31
+ option nil, :description, "Specify the description of the service", argument: :required
32
+ option nil, :'support-email', "Specify the support email of the service", argument: :required
33
+
34
+ runner CreateSubcommand
54
35
  end
55
36
  end
37
+
38
+ def run
39
+ service = Entities::Service.create(remote: remote, service_params: create_params)
40
+ printer.print_record service.attrs
41
+ end
42
+
43
+ private
44
+
45
+ def remote
46
+ @remote ||= threescale_client(arguments[:remote])
47
+ end
48
+
49
+ def parse_options
50
+ {
51
+ "deployment_option" => options[:'deployment-mode'],
52
+ "system_name" => options[:'system-name'],
53
+ "backend_version" => options[:'authentication-mode'],
54
+ "description" => options[:description],
55
+ "support_email" => options[:'support-email'],
56
+ }.compact
57
+ end
58
+
59
+ def create_params
60
+ service_name = arguments[:service_name]
61
+ create_service_attrs = parse_options
62
+ create_service_attrs['name'] = service_name
63
+ create_service_attrs
64
+ end
65
+
66
+ def printer
67
+ # keep backwards compatibility
68
+ options.fetch(:output, CustomPrinter.new)
69
+ end
56
70
  end
57
71
  end
58
72
  end
@@ -1,46 +1,44 @@
1
1
  module ThreeScaleToolbox
2
2
  module Commands
3
3
  module ServiceCommand
4
- module Delete
5
- class DeleteSubcommand < Cri::CommandRunner
6
- include ThreeScaleToolbox::Command
7
-
8
- def self.command
9
- Cri::Command.define do
10
- name 'delete'
11
- usage 'delete <remote> <service-id_or_system-name>'
12
- summary 'Delete a service'
13
- description 'Delete a service'
14
- runner DeleteSubcommand
15
-
16
- param :remote
17
- param :service_id_or_system_name
18
- end
4
+ class DeleteSubcommand < Cri::CommandRunner
5
+ include ThreeScaleToolbox::Command
6
+
7
+ def self.command
8
+ Cri::Command.define do
9
+ name 'delete'
10
+ usage 'delete <remote> <service-id_or_system-name>'
11
+ summary 'Delete a service'
12
+ description 'Delete a service'
13
+ runner DeleteSubcommand
14
+
15
+ param :remote
16
+ param :service_id_or_system_name
19
17
  end
18
+ end
20
19
 
21
- def run
22
- service.delete
23
- puts "Service with id: #{service.id} deleted"
24
- end
20
+ def run
21
+ service.delete
22
+ puts "Service with id: #{service.id} deleted"
23
+ end
25
24
 
26
- private
25
+ private
27
26
 
28
- def remote
29
- @remote ||= threescale_client(arguments[:remote])
30
- end
27
+ def remote
28
+ @remote ||= threescale_client(arguments[:remote])
29
+ end
31
30
 
32
- def ref
33
- @ref ||= arguments[:service_id_or_system_name]
34
- end
31
+ def ref
32
+ @ref ||= arguments[:service_id_or_system_name]
33
+ end
35
34
 
36
- def service
37
- @service ||= find_service
38
- end
35
+ def service
36
+ @service ||= find_service
37
+ end
39
38
 
40
- def find_service
41
- Entities::Service::find(remote: remote, ref: ref).tap do |svc|
42
- raise ThreeScaleToolbox::Error, "Service #{ref} does not exist" if svc.nil?
43
- end
39
+ def find_service
40
+ Entities::Service::find(remote: remote, ref: ref).tap do |svc|
41
+ raise ThreeScaleToolbox::Error, "Service #{ref} does not exist" if svc.nil?
44
42
  end
45
43
  end
46
44
  end
@@ -1,48 +1,38 @@
1
1
  module ThreeScaleToolbox
2
2
  module Commands
3
3
  module ServiceCommand
4
- module List
5
- class ListSubcommand < Cri::CommandRunner
6
- include ThreeScaleToolbox::Command
7
-
8
- def self.command
9
- Cri::Command.define do
10
- name 'list'
11
- usage 'list <remote>'
12
- summary 'List all services'
13
- description 'List all services'
14
- runner ListSubcommand
15
-
16
- param :remote
17
- end
18
- end
4
+ class ListSubcommand < Cri::CommandRunner
5
+ include ThreeScaleToolbox::Command
19
6
 
20
- def run
21
- print_header
22
- print_data
23
- end
7
+ FIELDS = %w[id name system_name]
24
8
 
25
- private
9
+ def self.command
10
+ Cri::Command.define do
11
+ name 'list'
12
+ usage 'list <remote>'
13
+ summary 'List all services'
14
+ description 'List all services'
26
15
 
27
- SERVICE_FIELDS_TO_SHOW = %w[id name system_name]
16
+ ThreeScaleToolbox::CLI.output_flag(self)
17
+ param :remote
28
18
 
29
- def services
30
- @services ||= remote.list_services()
19
+ runner ListSubcommand
31
20
  end
21
+ end
32
22
 
33
- def remote
34
- @remote ||= threescale_client(arguments[:remote])
35
- end
23
+ def run
24
+ printer.print_collection remote.list_services
25
+ end
36
26
 
37
- def print_header
38
- puts SERVICE_FIELDS_TO_SHOW.map { |e| e.upcase }.join("\t")
39
- end
27
+ private
40
28
 
41
- def print_data
42
- services.each do |service|
43
- puts SERVICE_FIELDS_TO_SHOW.map { |field| service.fetch(field, '(empty)') }.join("\t")
44
- end
45
- end
29
+ def remote
30
+ @remote ||= threescale_client(arguments[:remote])
31
+ end
32
+
33
+ def printer
34
+ # keep backwards compatibility
35
+ options.fetch(:output, CLI::CustomTablePrinter.new(FIELDS))
46
36
  end
47
37
  end
48
38
  end