morpheus-cli 4.2.16 → 4.2.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/README.md +8 -6
  4. data/lib/morpheus/api/api_client.rb +32 -14
  5. data/lib/morpheus/api/auth_interface.rb +4 -2
  6. data/lib/morpheus/api/backup_jobs_interface.rb +9 -0
  7. data/lib/morpheus/api/backups_interface.rb +16 -0
  8. data/lib/morpheus/api/deploy_interface.rb +25 -56
  9. data/lib/morpheus/api/deployments_interface.rb +43 -54
  10. data/lib/morpheus/api/doc_interface.rb +57 -0
  11. data/lib/morpheus/api/instances_interface.rb +5 -0
  12. data/lib/morpheus/api/rest_interface.rb +40 -0
  13. data/lib/morpheus/api/user_sources_interface.rb +0 -15
  14. data/lib/morpheus/api/users_interface.rb +2 -3
  15. data/lib/morpheus/benchmarking.rb +2 -2
  16. data/lib/morpheus/cli.rb +3 -1
  17. data/lib/morpheus/cli/access_token_command.rb +27 -10
  18. data/lib/morpheus/cli/apps.rb +21 -15
  19. data/lib/morpheus/cli/backup_jobs_command.rb +276 -0
  20. data/lib/morpheus/cli/backups_command.rb +271 -0
  21. data/lib/morpheus/cli/boot_scripts_command.rb +1 -1
  22. data/lib/morpheus/cli/cli_command.rb +92 -41
  23. data/lib/morpheus/cli/clusters.rb +0 -18
  24. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +7 -7
  25. data/lib/morpheus/cli/commands/standard/man_command.rb +1 -1
  26. data/lib/morpheus/cli/credentials.rb +13 -9
  27. data/lib/morpheus/cli/deploy.rb +374 -0
  28. data/lib/morpheus/cli/deployments.rb +521 -197
  29. data/lib/morpheus/cli/deploys.rb +271 -126
  30. data/lib/morpheus/cli/doc.rb +182 -0
  31. data/lib/morpheus/cli/error_handler.rb +23 -8
  32. data/lib/morpheus/cli/errors.rb +3 -2
  33. data/lib/morpheus/cli/image_builder_command.rb +2 -2
  34. data/lib/morpheus/cli/instances.rb +136 -17
  35. data/lib/morpheus/cli/invoices_command.rb +51 -38
  36. data/lib/morpheus/cli/library_layouts_command.rb +1 -1
  37. data/lib/morpheus/cli/login.rb +9 -3
  38. data/lib/morpheus/cli/mixins/accounts_helper.rb +158 -100
  39. data/lib/morpheus/cli/mixins/backups_helper.rb +115 -0
  40. data/lib/morpheus/cli/mixins/deployments_helper.rb +135 -0
  41. data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
  42. data/lib/morpheus/cli/mixins/print_helper.rb +110 -74
  43. data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -2
  44. data/lib/morpheus/cli/mixins/whoami_helper.rb +19 -6
  45. data/lib/morpheus/cli/network_routers_command.rb +1 -1
  46. data/lib/morpheus/cli/option_parser.rb +48 -5
  47. data/lib/morpheus/cli/option_types.rb +1 -1
  48. data/lib/morpheus/cli/remote.rb +3 -2
  49. data/lib/morpheus/cli/roles.rb +49 -92
  50. data/lib/morpheus/cli/security_groups.rb +7 -1
  51. data/lib/morpheus/cli/service_plans_command.rb +10 -10
  52. data/lib/morpheus/cli/setup.rb +1 -1
  53. data/lib/morpheus/cli/shell.rb +7 -6
  54. data/lib/morpheus/cli/subnets_command.rb +1 -1
  55. data/lib/morpheus/cli/tenants_command.rb +133 -163
  56. data/lib/morpheus/cli/user_groups_command.rb +20 -65
  57. data/lib/morpheus/cli/user_settings_command.rb +115 -13
  58. data/lib/morpheus/cli/user_sources_command.rb +57 -24
  59. data/lib/morpheus/cli/users.rb +210 -186
  60. data/lib/morpheus/cli/version.rb +1 -1
  61. data/lib/morpheus/cli/whitelabel_settings_command.rb +29 -5
  62. data/lib/morpheus/cli/whoami.rb +113 -6
  63. data/lib/morpheus/cli/workflows.rb +1 -1
  64. data/lib/morpheus/ext/hash.rb +21 -0
  65. data/lib/morpheus/terminal.rb +1 -0
  66. metadata +12 -3
  67. data/lib/morpheus/cli/auth_command.rb +0 -105
@@ -0,0 +1,271 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ class Morpheus::Cli::BackupsCommand
4
+ include Morpheus::Cli::CliCommand
5
+ include Morpheus::Cli::BackupsHelper
6
+ include Morpheus::Cli::ProvisioningHelper
7
+ include Morpheus::Cli::OptionSourceHelper
8
+
9
+ set_command_hidden # hide until ready
10
+
11
+ set_command_name :'backups'
12
+
13
+ register_subcommands :list, :get, :add, :update, :remove, :run, :restore
14
+
15
+ def connect(opts)
16
+ @api_client = establish_remote_appliance_connection(opts)
17
+ @backups_interface = @api_client.backups
18
+ @backup_jobs_interface = @api_client.backup_jobs
19
+ end
20
+
21
+ def handle(args)
22
+ handle_subcommand(args)
23
+ end
24
+
25
+ def list(args)
26
+ options = {}
27
+ params = {}
28
+ ref_ids = []
29
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
30
+ opts.banner = subcommand_usage("[search]")
31
+ build_standard_list_options(opts, options)
32
+ opts.footer = "List backups."
33
+ end
34
+ optparse.parse!(args)
35
+ connect(options)
36
+ # verify_args!(args:args, optparse:optparse, count:0)
37
+ if args.count > 0
38
+ options[:phrase] = args.join(" ")
39
+ end
40
+ params.merge!(parse_list_options(options))
41
+ @backups_interface.setopts(options)
42
+ if options[:dry_run]
43
+ print_dry_run @backups_interface.dry.list(params)
44
+ return
45
+ end
46
+ json_response = @backups_interface.list(params)
47
+ backups = json_response['backups']
48
+ render_response(json_response, options, 'backups') do
49
+ print_h1 "Morpheus Backups", parse_list_subtitles(options), options
50
+ if backups.empty?
51
+ print cyan,"No backups found.",reset,"\n"
52
+ else
53
+ print as_pretty_table(backups, backup_column_definitions.upcase_keys!, options)
54
+ print_results_pagination(json_response)
55
+ end
56
+ print reset,"\n"
57
+ end
58
+ if backups.empty?
59
+ return 1, "no backups found"
60
+ else
61
+ return 0, nil
62
+ end
63
+ end
64
+
65
+ def get(args)
66
+ params = {}
67
+ options = {}
68
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
69
+ opts.banner = subcommand_usage("[backup]")
70
+ build_standard_get_options(opts, options)
71
+ opts.footer = <<-EOT
72
+ Get details about a specific backup.
73
+ [backup] is required. This is the name or id of a backup.
74
+ EOT
75
+ end
76
+ optparse.parse!(args)
77
+ verify_args!(args:args, optparse:optparse, min:1)
78
+ connect(options)
79
+ id_list = parse_id_list(args)
80
+ return run_command_for_each_arg(id_list) do |arg|
81
+ _get(arg, params, options)
82
+ end
83
+ end
84
+
85
+ def _get(id, options)
86
+ params = {}
87
+ @backups_interface.setopts(options)
88
+ if options[:dry_run]
89
+ print_dry_run @backups_interface.dry.get(id, params)
90
+ return
91
+ end
92
+ json_response = @backups_interface.get(id, params)
93
+ backup = json_response['backup']
94
+ render_response(json_response, options, 'backup') do
95
+ print_h1 "Backup Details", [], options
96
+ print cyan
97
+ print_description_list(backup_column_definitions, backup)
98
+ print reset,"\n"
99
+ end
100
+ return 0, nil
101
+ end
102
+
103
+ def add(args)
104
+ options = {}
105
+ params = {}
106
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
107
+ opts.banner = subcommand_usage("[name] [options]")
108
+ build_option_type_options(opts, options, add_backup_option_types)
109
+ build_option_type_options(opts, options, add_backup_advanced_option_types)
110
+ build_standard_add_options(opts, options)
111
+ opts.footer = <<-EOT
112
+ Create a new backup.
113
+ EOT
114
+ end
115
+ optparse.parse!(args)
116
+ verify_args!(args:args, optparse:optparse, min:0, max:1)
117
+ options[:options]['name'] = args[0] if args[0]
118
+ connect(options)
119
+ payload = {}
120
+ if options[:payload]
121
+ payload = options[:payload]
122
+ payload.deep_merge!({'backup' => parse_passed_options(options)})
123
+ else
124
+ payload.deep_merge!({'backup' => parse_passed_options(options)})
125
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(add_backup_option_types(), options[:options], @api_client, options[:params])
126
+ params.deep_merge!(v_prompt)
127
+ advanced_config = Morpheus::Cli::OptionTypes.no_prompt(add_backup_advanced_option_types, options[:options], @api_client, options[:params])
128
+ advanced_config.deep_compact!
129
+ params.deep_merge!(advanced_config)
130
+ payload['backup'].deep_merge!(params)
131
+ end
132
+ @backups_interface.setopts(options)
133
+ if options[:dry_run]
134
+ print_dry_run @backups_interface.dry.create(payload)
135
+ return 0, nil
136
+ end
137
+ json_response = @backups_interface.create(payload)
138
+ backup = json_response['backup']
139
+ render_response(json_response, options, 'backup') do
140
+ print_green_success "Added backup #{backup['name']}"
141
+ return _get(backup["id"], {}, options)
142
+ end
143
+ return 0, nil
144
+ end
145
+
146
+ def update(args)
147
+ options = {}
148
+ params = {}
149
+ payload = {}
150
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
151
+ opts.banner = subcommand_usage("[backup] [options]")
152
+ build_option_type_options(opts, options, update_backup_option_types)
153
+ build_option_type_options(opts, options, update_backup_advanced_option_types)
154
+ build_standard_update_options(opts, options)
155
+ opts.footer = <<-EOT
156
+ Update a backup.
157
+ [backup] is required. This is the name or id of a backup.
158
+ EOT
159
+ end
160
+ optparse.parse!(args)
161
+ verify_args!(args:args, optparse:optparse, count:1)
162
+ connect(options)
163
+ backup = find_backup_by_name_or_id(args[0])
164
+ return 1 if backup.nil?
165
+ payload = {}
166
+ if options[:payload]
167
+ payload = options[:payload]
168
+ payload.deep_merge!({'backup' => parse_passed_options(options)})
169
+ else
170
+ payload.deep_merge!({'backup' => parse_passed_options(options)})
171
+ # do not prompt on update
172
+ v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_backup_option_types, options[:options], @api_client, options[:params])
173
+ v_prompt.deep_compact!
174
+ params.deep_merge!(v_prompt)
175
+ advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_backup_advanced_option_types, options[:options], @api_client, options[:params])
176
+ advanced_config.deep_compact!
177
+ params.deep_merge!(advanced_config)
178
+ payload.deep_merge!({'backup' => params})
179
+ if payload['backup'].empty? # || options[:no_prompt]
180
+ raise_command_error "Specify at least one option to update.\n#{optparse}"
181
+ end
182
+ end
183
+ @backups_interface.setopts(options)
184
+ if options[:dry_run]
185
+ print_dry_run @backups_interface.dry.update(backup['id'], payload)
186
+ return
187
+ end
188
+ json_response = @backups_interface.update(backup['id'], payload)
189
+ backup = json_response['backup']
190
+ render_response(json_response, options, 'backup') do
191
+ print_green_success "Updated backup #{backup['name']}"
192
+ return _get(backup["id"], {}, options)
193
+ end
194
+ return 0, nil
195
+ end
196
+
197
+ def remove(args)
198
+ options = {}
199
+ params = {}
200
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
201
+ opts.banner = subcommand_usage("[backup] [options]")
202
+ build_standard_remove_options(opts, options)
203
+ opts.footer = <<-EOT
204
+ Delete a backup.
205
+ [backup] is required. This is the name or id of a backup.
206
+ EOT
207
+ end
208
+ optparse.parse!(args)
209
+ verify_args!(args:args, optparse:optparse, count:1)
210
+ connect(options)
211
+ backup = find_backup_by_name_or_id(args[0])
212
+ return 1 if backup.nil?
213
+ @backups_interface.setopts(options)
214
+ if options[:dry_run]
215
+ print_dry_run @backups_interface.dry.destroy(backup['id'], params)
216
+ return
217
+ end
218
+ json_response = @backups_interface.destroy(backup['id'], params)
219
+ render_response(json_response, options) do
220
+ print_green_success "Removed backup #{backup['name']}"
221
+ end
222
+ return 0, nil
223
+ end
224
+
225
+ private
226
+
227
+ def backup_column_definitions()
228
+ {
229
+ "ID" => 'id',
230
+ "Name" => 'name',
231
+ "Schedule" => lambda {|it| it['schedule']['name'] rescue '' },
232
+ "Backup Job" => lambda {|it| it['job']['name'] rescue '' },
233
+ "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
234
+ "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
235
+ }
236
+ end
237
+
238
+ # this is not so simple, need to first choose select instance, host or provider
239
+ def add_backup_option_types
240
+ [
241
+ {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
242
+ {'fieldName' => 'jobId', 'fieldLabel' => 'Backup Job', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
243
+ # @options_interface.options_for_source("licenseTypes", {})['data']
244
+ @backup_jobs_interface.list({max:10000})['backupJobs'].collect {|backup_job|
245
+ {'name' => backup_job['name'], 'value' => backup_job['id'], 'id' => backup_job['id']}
246
+ }
247
+ }, 'required' => true, 'displayOrder' => 3},
248
+ ]
249
+ end
250
+
251
+ def add_backup_advanced_option_types
252
+ []
253
+ end
254
+
255
+ def update_backup_option_types
256
+ add_backup_option_types.collect {|it|
257
+ it.delete('required')
258
+ it.delete('defaultValue')
259
+ it
260
+ }
261
+ end
262
+
263
+ def update_backup_advanced_option_types
264
+ add_backup_advanced_option_types.collect {|it|
265
+ it.delete('required')
266
+ it.delete('defaultValue')
267
+ it
268
+ }
269
+ end
270
+
271
+ end
@@ -279,7 +279,7 @@ class Morpheus::Cli::BootScriptsCommand
279
279
  options = {}
280
280
  optparse = Morpheus::Cli::OptionParser.new do |opts|
281
281
  opts.banner = subcommand_usage("[boot-script]")
282
- build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run, :remote])
282
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
283
283
  end
284
284
  optparse.parse!(args)
285
285
 
@@ -1,5 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'json'
3
+ require 'fileutils'
3
4
  require 'morpheus/logging'
4
5
  require 'morpheus/benchmarking'
5
6
  require 'morpheus/cli/option_parser'
@@ -232,11 +233,11 @@ module Morpheus
232
233
  ## the standard options for a command that makes api requests (most of them)
233
234
 
234
235
  def build_standard_get_options(opts, options, includes=[], excludes=[])
235
- build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :quiet, :dry_run, :remote] + includes, excludes)
236
+ build_common_options(opts, options, includes + [:query, :json, :yaml, :csv, :fields, :quiet, :dry_run, :remote], excludes)
236
237
  end
237
238
 
238
239
  def build_standard_post_options(opts, options, includes=[], excludes=[])
239
- build_common_options(opts, options, [:options, :payload, :json, :quiet, :dry_run, :remote] + includes, excludes)
240
+ build_common_options(opts, options, includes + [:options, :payload, :json, :quiet, :dry_run, :remote], excludes)
240
241
  end
241
242
 
242
243
  def build_standard_put_options(opts, options, includes=[], excludes=[])
@@ -244,7 +245,7 @@ module Morpheus
244
245
  end
245
246
 
246
247
  def build_standard_delete_options(opts, options, includes=[], excludes=[])
247
- build_common_options(opts, options, [:auto_confirm, :query, :json, :quiet, :dry_run, :remote] + includes, excludes)
248
+ build_common_options(opts, options, includes + [:auto_confirm, :query, :json, :quiet, :dry_run, :remote], excludes)
248
249
  end
249
250
 
250
251
  # list is GET that supports phrase,max,offset,sort,direction
@@ -285,13 +286,24 @@ module Morpheus
285
286
  while (option_key = option_keys.shift) do
286
287
  case option_key.to_sym
287
288
 
288
- when :account
289
- opts.on('-a','--account ACCOUNT', "Account Name or ID") do |val|
289
+ when :tenant, :account
290
+ # todo: let's deprecate this in favor of :tenant --tenant to keep -a reserved for --all perhaps?
291
+ opts.on('--tenant TENANT', String, "Tenant (Account) Name or ID") do |val|
290
292
  options[:account] = val
291
293
  end
292
- opts.on('-A','--account-id ID', "Account ID") do |val|
294
+ opts.on('--tenant-id ID', String, "Tenant (Account) ID") do |val|
293
295
  options[:account_id] = val
294
296
  end
297
+ # todo: let's deprecate this in favor of :tenant --tenant to keep -a reserved for --all perhaps?
298
+ opts.on('-a','--account ACCOUNT', "Alias for --tenant") do |val|
299
+ options[:account] = val
300
+ end
301
+ opts.on('-A','--account-id ID', "Tenant (Account) ID") do |val|
302
+ options[:account_id] = val
303
+ end
304
+ opts.add_hidden_option('--tenant-id') if opts.is_a?(Morpheus::Cli::OptionParser)
305
+ opts.add_hidden_option('-a, --account') if opts.is_a?(Morpheus::Cli::OptionParser)
306
+ opts.add_hidden_option('-A, --account-id') if opts.is_a?(Morpheus::Cli::OptionParser)
295
307
 
296
308
  when :options
297
309
  options[:options] ||= {}
@@ -459,7 +471,7 @@ module Morpheus
459
471
  end
460
472
 
461
473
  # arbitrary query parameters in the format -Q "category=web&phrase=nginx"
462
- # opts.on( '-Q', '--query PARAMS', "Query parameters. PARAMS format is 'phrase=foobar&category=web'" ) do |val|
474
+ # opts.on( '-Q', '--query PARAMS', "Query parameters. PARAMS format is 'foo=bar&category=web'" ) do |val|
463
475
  # options[:query_filters_raw] = val
464
476
  # options[:query_filters] = {}
465
477
  # # todo: smarter parsing
@@ -477,7 +489,7 @@ module Morpheus
477
489
 
478
490
  when :query, :query_filters
479
491
  # arbitrary query parameters in the format -Q "category=web&phrase=nginx"
480
- opts.on( '-Q', '--query PARAMS', "Query parameters. PARAMS format is 'phrase=foobar&category=web'" ) do |val|
492
+ opts.on( '-Q', '--query PARAMS', "Query parameters. PARAMS format is 'foo=bar&category=web'" ) do |val|
481
493
  options[:query_filters_raw] = val
482
494
  options[:query_filters] = {}
483
495
  # todo: smarter parsing
@@ -603,9 +615,17 @@ module Morpheus
603
615
  opts.add_hidden_option('json-raw') if opts.is_a?(Morpheus::Cli::OptionParser)
604
616
 
605
617
  when :yaml
606
- opts.on(nil, '--yaml', "YAML Output") do
607
- options[:yaml] = true
608
- options[:format] = :yaml
618
+ # -y for --yes and for --yaml
619
+ if includes.include?(:auto_confirm)
620
+ opts.on(nil, '--yaml', "YAML Output") do
621
+ options[:yaml] = true
622
+ options[:format] = :yaml
623
+ end
624
+ else
625
+ opts.on('-y', '--yaml', "YAML Output") do
626
+ options[:yaml] = true
627
+ options[:format] = :yaml
628
+ end
609
629
  end
610
630
  opts.on(nil, '--yml', "alias for --yaml") do
611
631
  options[:yaml] = true
@@ -783,7 +803,11 @@ module Morpheus
783
803
  end
784
804
  opts.add_hidden_option('--no-debug') if opts.is_a?(Morpheus::Cli::OptionParser)
785
805
 
786
-
806
+ opts.on('--hidden-help', "Print help that includes all the hidden options, like this one." ) do
807
+ puts opts.full_help_message({show_hidden_options:true})
808
+ exit # return 0 maybe?
809
+ end
810
+ opts.add_hidden_option('--hidden-help') if opts.is_a?(Morpheus::Cli::OptionParser)
787
811
  opts.on('-h', '--help', "Print this help" ) do
788
812
  puts opts
789
813
  exit # return 0 maybe?
@@ -1011,7 +1035,7 @@ module Morpheus
1011
1035
  # raise_command_error "Please specify a remote appliance with -r or see the command `remote use`"
1012
1036
  # end
1013
1037
 
1014
- Morpheus::Logging::DarkPrinter.puts "establishing connection to remote #{display_appliance(@appliance_name, @appliance_url)}" if Morpheus::Logging.debug?
1038
+ Morpheus::Logging::DarkPrinter.puts "establishing connection to remote #{display_appliance(@appliance_name, @appliance_url)}" if Morpheus::Logging.debug? # && !options[:quiet]
1015
1039
 
1016
1040
  if options[:no_authorization]
1017
1041
  # maybe handle this here..
@@ -1082,7 +1106,7 @@ module Morpheus
1082
1106
  else
1083
1107
  if opts[:min]
1084
1108
  if args.count < opts[:min]
1085
- raise_args_error("not many arguments, expected #{opts[:min] || '0'}-#{opts[:max] || 'N'} and got #{args.count == 0 ? '0' : args.count.to_s + ': '}#{args.join(', ')}", args, opts[:optparse])
1109
+ raise_args_error("not enough arguments, expected #{opts[:min] || '0'}-#{opts[:max] || 'N'} and got #{args.count == 0 ? '0' : args.count.to_s + ': '}#{args.join(', ')}", args, opts[:optparse])
1086
1110
  end
1087
1111
  end
1088
1112
  if opts[:max]
@@ -1173,22 +1197,32 @@ module Morpheus
1173
1197
  payload
1174
1198
  end
1175
1199
 
1176
- def render_response(json_response, options, object_key=nil, &block)
1177
- render_result = render_with_format(json_response, options, object_key)
1178
- if render_result
1179
- return 0, nil
1180
- else
1181
- if block_given?
1182
- return yield
1200
+ def validate_outfile(outfile, options)
1201
+ full_filename = File.expand_path(outfile)
1202
+ outdir = File.dirname(full_filename)
1203
+ if Dir.exists?(full_filename)
1204
+ print_red_alert "[local-file] is invalid. It is the name of an existing directory: #{outfile}"
1205
+ return false
1206
+ end
1207
+ if !Dir.exists?(outdir)
1208
+ if options[:mkdir]
1209
+ print cyan,"Creating local directory #{outdir}",reset,"\n"
1210
+ FileUtils.mkdir_p(outdir)
1183
1211
  else
1184
- return 0, nil
1212
+ print_red_alert "[local-file] is invalid. Directory not found: #{outdir}"
1213
+ return false
1185
1214
  end
1186
1215
  end
1216
+ if File.exists?(full_filename) && !options[:overwrite]
1217
+ print_red_alert "[local-file] is invalid. File already exists: #{outfile}\nUse -f to overwrite the existing file."
1218
+ return false
1219
+ end
1220
+ return true
1187
1221
  end
1188
1222
 
1189
1223
  # basic rendering for options :json, :yml, :csv, :quiet, and :outfile
1190
1224
  # returns the string rendered, or nil if nothing was rendered.
1191
- def render_with_format(json_response, options, object_key=nil, &block)
1225
+ def render_response(json_response, options, object_key=nil, &block)
1192
1226
  output = nil
1193
1227
  if options[:json]
1194
1228
  output = as_json(json_response, options, object_key)
@@ -1201,32 +1235,49 @@ module Morpheus
1201
1235
  else
1202
1236
  output = records_as_csv([row], options)
1203
1237
  end
1204
- elsif options[:quiet]
1205
- # note: returning non nil means the calling function knows to return rght away.. kinda weird..
1206
- # but means we need less if options[:quiet] blocks in every action.
1207
- return ""
1208
1238
  end
1209
- if output
1210
- if options[:outfile]
1239
+ if options[:outfile]
1240
+ if output
1211
1241
  print_to_file(output, options[:outfile], options[:overwrite])
1242
+ print "#{cyan}Wrote output to file #{options[:outfile]} (#{File.size(options[:outfile])} B)\n" unless options[:quiet]
1212
1243
  else
1213
- puts output
1244
+ # uhhh ok lets try this
1245
+ Morpheus::Logging::DarkPrinter.puts "using experimental feature: --outfile without a common format like json, yml or csv" if Morpheus::Logging.debug?
1246
+ result = with_stdout_to_file(options[:outfile], options[:overwrite], 'w+', &block)
1247
+ print "#{cyan}Wrote output to file #{options[:outfile]} (#{File.size(options[:outfile])} B)\n" unless options[:quiet]
1248
+ if result
1249
+ return result
1250
+ end
1251
+ return 0, nil
1214
1252
  end
1215
1253
  else
1216
- if block_given?
1217
- # invoke the user given block to render (print output)
1218
- # hope it returned something well formed, there's a parse method for that..
1219
- cmd_render_result = yield
1220
- # could try to support writing output to options[:outfile] here too..
1221
- # output is already printed inside block though
1222
- # if cmd_render_result
1223
- # return output
1224
- # end
1225
- end
1254
+ # --quiet means do not render, still want to print to outfile though
1255
+ if options[:quiet]
1256
+ return 0, nil
1257
+ end
1258
+ # render ouput generated above
1259
+ if output
1260
+ puts output
1261
+ return 0, nil
1262
+ else
1263
+ # no render happened, so calling the block if given
1264
+ if block_given?
1265
+ result = yield
1266
+ if result
1267
+ return result
1268
+ else
1269
+ return 0, nil
1270
+ end
1271
+ else
1272
+ # nil means nothing was rendered, some methods still using render_with_format() are relying on this
1273
+ return nil
1274
+ end
1275
+ end
1226
1276
  end
1227
- return output
1228
1277
  end
1229
1278
 
1279
+ alias :render_with_format :render_response
1280
+
1230
1281
  module ClassMethods
1231
1282
 
1232
1283
  def set_command_name(cmd_name)