morpheus-cli 4.2.16 → 4.2.17

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 (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)