morpheus-cli 2.12.5 → 3.1.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -0
  3. data/lib/morpheus/api/api_client.rb +15 -30
  4. data/lib/morpheus/api/app_templates_interface.rb +34 -7
  5. data/lib/morpheus/api/apps_interface.rb +20 -1
  6. data/lib/morpheus/api/archive_buckets_interface.rb +124 -0
  7. data/lib/morpheus/api/archive_files_interface.rb +182 -0
  8. data/lib/morpheus/api/{network_pools_interface.rb → image_builder_boot_scripts_interface.rb} +6 -6
  9. data/lib/morpheus/api/{policies_interface.rb → image_builder_image_builds_interface.rb} +20 -15
  10. data/lib/morpheus/api/image_builder_interface.rb +26 -0
  11. data/lib/morpheus/api/{network_proxies_interface.rb → image_builder_preseed_scripts_interface.rb} +6 -6
  12. data/lib/morpheus/cli.rb +10 -9
  13. data/lib/morpheus/cli/alias_command.rb +10 -9
  14. data/lib/morpheus/cli/app_templates.rb +1566 -457
  15. data/lib/morpheus/cli/apps.rb +284 -108
  16. data/lib/morpheus/cli/archives_command.rb +2184 -0
  17. data/lib/morpheus/cli/boot_scripts_command.rb +382 -0
  18. data/lib/morpheus/cli/cli_command.rb +9 -35
  19. data/lib/morpheus/cli/error_handler.rb +2 -0
  20. data/lib/morpheus/cli/hosts.rb +15 -3
  21. data/lib/morpheus/cli/image_builder_command.rb +1208 -0
  22. data/lib/morpheus/cli/instances.rb +118 -47
  23. data/lib/morpheus/cli/man_command.rb +27 -24
  24. data/lib/morpheus/cli/mixins/print_helper.rb +19 -5
  25. data/lib/morpheus/cli/mixins/provisioning_helper.rb +20 -20
  26. data/lib/morpheus/cli/option_types.rb +45 -14
  27. data/lib/morpheus/cli/preseed_scripts_command.rb +381 -0
  28. data/lib/morpheus/cli/remote.rb +1 -0
  29. data/lib/morpheus/cli/roles.rb +2 -2
  30. data/lib/morpheus/cli/shell.rb +3 -2
  31. data/lib/morpheus/cli/version.rb +1 -1
  32. data/lib/morpheus/ext/hash.rb +22 -0
  33. data/lib/morpheus/formatters.rb +33 -0
  34. data/lib/morpheus/terminal.rb +1 -1
  35. metadata +13 -21
  36. data/lib/morpheus/api/cloud_policies_interface.rb +0 -47
  37. data/lib/morpheus/api/group_policies_interface.rb +0 -47
  38. data/lib/morpheus/api/network_domains_interface.rb +0 -47
  39. data/lib/morpheus/api/network_groups_interface.rb +0 -47
  40. data/lib/morpheus/api/network_pool_servers_interface.rb +0 -47
  41. data/lib/morpheus/api/network_services_interface.rb +0 -47
  42. data/lib/morpheus/api/networks_interface.rb +0 -54
  43. data/lib/morpheus/cli/network_domains_command.rb +0 -571
  44. data/lib/morpheus/cli/network_groups_command.rb +0 -602
  45. data/lib/morpheus/cli/network_pool_servers_command.rb +0 -430
  46. data/lib/morpheus/cli/network_pools_command.rb +0 -495
  47. data/lib/morpheus/cli/network_proxies_command.rb +0 -594
  48. data/lib/morpheus/cli/network_services_command.rb +0 -148
  49. data/lib/morpheus/cli/networks_command.rb +0 -855
  50. data/lib/morpheus/cli/policies_command.rb +0 -847
  51. data/scripts/generate_morpheus_commands_help.morpheus +0 -1313
@@ -28,6 +28,7 @@ class Morpheus::Cli::Instances
28
28
  @tasks_interface = @api_client.tasks
29
29
  @instance_types_interface = @api_client.instance_types
30
30
  @clouds_interface = @api_client.clouds
31
+ @servers_interface = @api_client.servers
31
32
  @provision_types_interface = @api_client.provision_types
32
33
  @options_interface = @api_client.options
33
34
  @active_group_id = Morpheus::Cli::Groups.active_group
@@ -47,6 +48,9 @@ class Morpheus::Cli::Instances
47
48
  opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
48
49
  options[:cloud] = val
49
50
  end
51
+ opts.on( '-H', '--host HOST', "Host Name or ID" ) do |val|
52
+ options[:host] = val
53
+ end
50
54
  build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
51
55
  end
52
56
  optparse.parse!(args)
@@ -65,6 +69,11 @@ class Morpheus::Cli::Instances
65
69
  params['zoneId'] = cloud['id']
66
70
  end
67
71
 
72
+ host = options[:host] ? find_host_by_name_or_id(options[:host]) : options[:host]
73
+ if host
74
+ params['serverId'] = host['id']
75
+ end
76
+
68
77
  [:phrase, :offset, :max, :sort, :direction].each do |k|
69
78
  params[k] = options[k] unless options[k].nil?
70
79
  end
@@ -106,6 +115,9 @@ class Morpheus::Cli::Instances
106
115
  if cloud
107
116
  subtitles << "Cloud: #{cloud['name']}".strip
108
117
  end
118
+ if host
119
+ subtitles << "Host: #{host['name']}".strip
120
+ end
109
121
  if params[:phrase]
110
122
  subtitles << "Search: #{params[:phrase]}".strip
111
123
  end
@@ -203,51 +215,69 @@ class Morpheus::Cli::Instances
203
215
  opts.on("--create-backup on|off", String, "Automation: Create Backups. Default is off") do |val|
204
216
  options[:create_backup] = ['on','true','1'].include?(val.to_s.downcase) ? 'on' : 'off'
205
217
  end
206
- build_common_options(opts, options, [:options, :json, :dry_run, :remote])
218
+ opts.on('--config JSON', String, "Instance Config JSON. This skips prompting and the above options are ignored.") do |val|
219
+ options['config'] = JSON.parse(val.to_s)
220
+ end
221
+ opts.on('--config-yaml YAML', String, "Instance Config YAML. This skips prompting and the above options are ignored.") do |val|
222
+ options['config'] = YAML.load(val.to_s)
223
+ end
224
+ opts.on('--config-file FILE', String, "Instance Config from a local JSON or YAML file. This skips prompting and the above options are ignored.") do |val|
225
+ options['configFile'] = val.to_s
226
+ end
227
+ build_common_options(opts, options, [:options, :json, :dry_run, :remote, :quiet])
207
228
  end
208
229
 
209
230
  optparse.parse!(args)
210
231
  connect(options)
211
232
 
212
- # this is the old format of `instance add TYPE NAME`
213
- # JD: it seems confusing, let's deprecate and go with `instances add [NAME] -t TYPE`
214
- if args[0]
215
- options[:instance_type_code] = args[0]
233
+ if args.count > 1
234
+ print_error Morpheus::Terminal.angry_prompt
235
+ puts_error "#{command_name} add has just 1 (optional) argument: [name]. Got #{args.count} arguments: #{args.join(' ')}\n#{optparse}"
236
+ return 1
216
237
  end
217
- if args[1]
218
- options[:instance_name] = args[1]
238
+ if args[0]
239
+ options[:instance_name] = args[0]
219
240
  end
220
241
 
221
- # if args.count > 1
222
- # print_error Morpheus::Terminal.angry_prompt
223
- # puts_error "#{command_name} add has just 1 (optional) argument: NAME. Got #{args.count} arguments: #{args.join(', ')}\n#{optparse}"
224
- # return 1
225
- # end
226
- # if args[0]
227
- # options[:instance_name] = args[0]
228
- # end
229
-
230
242
  # use active group by default
231
243
  options[:group] ||= @active_group_id
232
244
 
233
245
  options[:name_required] = true
234
246
  begin
235
- # this provisioning helper method handles all (most) of the parsing and prompting
236
- # and it relies on the method to exit non-zero on error, like a bad CLOUD or TYPE value
237
- payload = prompt_new_instance(options)
238
-
239
- # other stuff
240
- payload[:copies] = options[:copies] if options[:copies] && options[:copies] > 0
241
- payload[:layoutSize] = options[:layout_size] if options[:layout_size] && options[:layout_size] > 0 # aka Scale Factor
242
- payload[:createBackup] = options[:create_backup] ? 'on' : 'off' if options[:create_backup] == true
243
- payload['instance']['expireDays'] = options[:expire_days] if options[:expire_days]
244
- payload['instance']['shutdownDays'] = options[:shutdown_days] if options[:shutdown_days]
245
- if options[:workflow_id]
246
- payload['taskSetId'] = options[:workflow_id]
247
- end
248
- if options[:enable_load_balancer]
249
- lb_payload = prompt_instance_load_balancer(payload['instance'], nil, options)
250
- payload.deep_merge!(lb_payload)
247
+ payload = nil
248
+ if options['config']
249
+ payload = options['config']
250
+ elsif options['configFile']
251
+ config_file = File.expand_path(options['configFile'])
252
+ if !File.exists?(config_file) || !File.file?(config_file)
253
+ print_red_alert "File not found: #{config_file}"
254
+ return false
255
+ end
256
+ config_payload = {}
257
+ if config_file =~ /\.ya?ml\Z/
258
+ config_payload = YAML.load_file(config_file)
259
+ else
260
+ config_payload = JSON.parse(File.read(config_file))
261
+ end
262
+ payload = config_payload
263
+ else
264
+ # prompt for all the instance configuration options
265
+ # this provisioning helper method handles all (most) of the parsing and prompting
266
+ # and it relies on the method to exit non-zero on error, like a bad CLOUD or TYPE value
267
+ payload = prompt_new_instance(options)
268
+ # other stuff
269
+ payload[:copies] = options[:copies] if options[:copies] && options[:copies] > 0
270
+ payload[:layoutSize] = options[:layout_size] if options[:layout_size] && options[:layout_size] > 0 # aka Scale Factor
271
+ payload[:createBackup] = options[:create_backup] ? 'on' : 'off' if options[:create_backup] == true
272
+ payload['instance']['expireDays'] = options[:expire_days] if options[:expire_days]
273
+ payload['instance']['shutdownDays'] = options[:shutdown_days] if options[:shutdown_days]
274
+ if options[:workflow_id]
275
+ payload['taskSetId'] = options[:workflow_id]
276
+ end
277
+ if options[:enable_load_balancer]
278
+ lb_payload = prompt_instance_load_balancer(payload['instance'], nil, options)
279
+ payload.deep_merge!(lb_payload)
280
+ end
251
281
  end
252
282
 
253
283
  if options[:dry_run]
@@ -258,9 +288,11 @@ class Morpheus::Cli::Instances
258
288
  json_response = @instances_interface.create(payload)
259
289
  if options[:json]
260
290
  puts as_json(json_response, options)
261
- else
291
+ elsif !options[:quiet]
292
+ instance_id = json_response["instance"]["id"]
262
293
  instance_name = json_response["instance"]["name"]
263
- print_green_success "Provisioning instance #{instance_name}"
294
+ print_green_success "Provisioning instance [#{instance_id}] #{instance_name}"
295
+ _get([instance_id])
264
296
  #list([])
265
297
  end
266
298
  return 0
@@ -424,7 +456,7 @@ class Morpheus::Cli::Instances
424
456
  opts.on( '-n', '--node NODE_ID', "Scope console to specific Container or VM" ) do |node_id|
425
457
  options[:node_id] = node_id.to_i
426
458
  end
427
- # build_common_options(opts, options, [:list, :json, :dry_run, :remote])
459
+ build_common_options(opts, options, [:remote])
428
460
  end
429
461
  optparse.parse!(args)
430
462
  if args.count < 1
@@ -480,10 +512,6 @@ class Morpheus::Cli::Instances
480
512
  params[k] = options[k] unless options[k].nil?
481
513
  end
482
514
  params[:query] = params.delete(:phrase) unless params[:phrase].nil?
483
- if options[:dry_run]
484
- print_dry_run @logs_interface.dry.server_logs([server['id']], params)
485
- return
486
- end
487
515
  if options[:dry_run]
488
516
  print_dry_run @logs_interface.dry.container_logs(container_ids, params)
489
517
  return
@@ -491,7 +519,8 @@ class Morpheus::Cli::Instances
491
519
  logs = @logs_interface.container_logs(container_ids, params)
492
520
  output = ""
493
521
  if options[:json]
494
- output << as_json(logs, options)
522
+ puts as_json(logs, options)
523
+ return 0
495
524
  else
496
525
  title = "Instance Logs: #{instance['name']} (#{instance['instanceType'] ? instance['instanceType']['name'] : ''})"
497
526
  subtitles = []
@@ -501,7 +530,7 @@ class Morpheus::Cli::Instances
501
530
  # todo: startMs, endMs, sorts insteaad of sort..etc
502
531
  print_h1 title, subtitles
503
532
  if logs['data'].empty?
504
- output << "#{cyan}No logs found.#{reset}\n"
533
+ puts "#{cyan}No logs found.#{reset}"
505
534
  else
506
535
  logs['data'].reverse.each do |log_entry|
507
536
  log_level = ''
@@ -517,10 +546,11 @@ class Morpheus::Cli::Instances
517
546
  when 'FATAL'
518
547
  log_level = "#{red}#{bold}FATAL#{reset}"
519
548
  end
520
- output << "[#{log_entry['ts']}] #{log_level} - #{log_entry['message']}\n"
549
+ puts "[#{log_entry['ts']}] #{log_level} - #{log_entry['message'].to_s.strip}"
521
550
  end
551
+ print output, reset, "\n"
552
+ return 0
522
553
  end
523
- print output, reset, "\n"
524
554
  end
525
555
  rescue RestClient::Exception => e
526
556
  print_rest_exception(e, options)
@@ -564,7 +594,7 @@ class Morpheus::Cli::Instances
564
594
  end
565
595
  end
566
596
 
567
- def _get(arg, options)
597
+ def _get(arg, options={})
568
598
  begin
569
599
  if options[:dry_run]
570
600
  if arg.to_s =~ /\A\d{1,}\Z/
@@ -1486,7 +1516,7 @@ class Morpheus::Cli::Instances
1486
1516
  puts "\nDue to limitations by most Guest Operating Systems, Disk sizes can only be expanded and not reduced.\nIf a smaller plan is selected, memory and CPU (if relevant) will be reduced but storage will not.\n\n"
1487
1517
 
1488
1518
  # prompt for service plan
1489
- service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, layoutId: layout_id})
1519
+ service_plans_json = @instances_interface.service_plans({zoneId: cloud_id, siteId: group_id, layoutId: layout_id})
1490
1520
  service_plans = service_plans_json["plans"]
1491
1521
  service_plans_dropdown = service_plans.collect {|sp| {'name' => sp["name"], 'value' => sp["id"]} } # already sorted
1492
1522
  service_plans_dropdown.each do |plan|
@@ -1572,12 +1602,18 @@ class Morpheus::Cli::Instances
1572
1602
  query_params = {keepBackups: 'off', force: 'off'}
1573
1603
  optparse = OptionParser.new do|opts|
1574
1604
  opts.banner = subcommand_usage("[name] [-fB]")
1575
- opts.on( '-f', '--force', "Force Remove" ) do
1605
+ opts.on( '-f', '--force', "Force Delete" ) do
1576
1606
  query_params[:force] = 'on'
1577
1607
  end
1578
1608
  opts.on( '-B', '--keep-backups', "Preserve copy of backups" ) do
1579
1609
  query_params[:keepBackups] = 'on'
1580
1610
  end
1611
+ opts.on('--remove-volumes [on|off]', ['on','off'], "Remove Volumes. Default is on. Applies to certain types only.") do |val|
1612
+ query_params[:removeVolumes] = val
1613
+ end
1614
+ opts.on('--releaseEIPs [on|off]', ['on','off'], "Release EIPs. Default is false. Applies to Amazon only.") do |val|
1615
+ query_params[:releaseEIPs] = val
1616
+ end
1581
1617
  build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
1582
1618
 
1583
1619
  end
@@ -2210,6 +2246,39 @@ private
2210
2246
  end
2211
2247
  return zone
2212
2248
  end
2249
+ def find_host_by_id(id)
2250
+ begin
2251
+ json_response = @servers_interface.get(id.to_i)
2252
+ return json_response['server']
2253
+ rescue RestClient::Exception => e
2254
+ if e.response && e.response.code == 404
2255
+ print_red_alert "Host not found by id #{id}"
2256
+ exit 1
2257
+ else
2258
+ raise e
2259
+ end
2260
+ end
2261
+ end
2262
+
2263
+ def find_host_by_name(name)
2264
+ results = @servers_interface.get({name: name})
2265
+ if results['servers'].empty?
2266
+ print_red_alert "Host not found by name #{name}"
2267
+ exit 1
2268
+ elsif results['servers'].size > 1
2269
+ print_red_alert "Multiple hosts exist with the name #{name}. Try using id instead"
2270
+ exit 1
2271
+ end
2272
+ return results['servers'][0]
2273
+ end
2274
+
2275
+ def find_host_by_name_or_id(val)
2276
+ if val.to_s =~ /\A\d{1,}\Z/
2277
+ return find_host_by_id(val)
2278
+ else
2279
+ return find_host_by_name(val)
2280
+ end
2281
+ end
2213
2282
 
2214
2283
  def find_workflow_by_name(name)
2215
2284
  task_set_results = @task_sets_interface.get(name)
@@ -2246,10 +2315,12 @@ private
2246
2315
  status_string = instance['status'].to_s
2247
2316
  if status_string == 'running'
2248
2317
  out << "#{green}#{status_string.upcase}#{return_color}"
2318
+ elsif status_string == 'provisioning'
2319
+ out << "#{cyan}#{status_string.upcase}#{return_color}"
2249
2320
  elsif status_string == 'stopped' or status_string == 'failed'
2250
2321
  out << "#{red}#{status_string.upcase}#{return_color}"
2251
2322
  elsif status_string == 'unknown'
2252
- out << "#{white}#{status_string.upcase}#{return_color}"
2323
+ out << "#{yellow}#{status_string.upcase}#{return_color}"
2253
2324
  else
2254
2325
  out << "#{yellow}#{status_string.upcase}#{return_color}"
2255
2326
  end
@@ -152,11 +152,12 @@ EOT
152
152
  FileUtils.chmod(0600, fn)
153
153
 
154
154
  manpage = File.new(fn, 'w')
155
- previous_stdout = $stdout
156
- $stdout = manpage
155
+ # previous_stdout = $stdout
156
+ # previous_stdout = STDOUT
157
+ # $stdout = manpage
157
158
  begin
158
159
 
159
- $stdout.print <<-ENDTEXT
160
+ manpage.print <<-ENDTEXT
160
161
  ## NAME
161
162
 
162
163
  morpheus - the command line interface for interacting with the Morpheus Data appliance
@@ -214,16 +215,16 @@ EOT
214
215
  The available commands and their options are also documented below.
215
216
  ENDTEXT
216
217
 
217
- terminal = Morpheus::Terminal.new($stdin, $stdout)
218
+ terminal = Morpheus::Terminal.new($stdin, manpage)
218
219
  Morpheus::Logging::DarkPrinter.puts "appending command help `morpheus --help`" if Morpheus::Logging.debug?
219
220
 
220
- $stdout.print "\n"
221
- $stdout.print "## morpheus\n"
222
- $stdout.print "\n"
223
- $stdout.print "```\n"
221
+ manpage.print "\n"
222
+ manpage.print "## morpheus\n"
223
+ manpage.print "\n"
224
+ manpage.print "```\n"
224
225
  exit_code, err = terminal.execute("--help")
225
- $stdout.print "```\n"
226
- $stdout.print "\n"
226
+ manpage.print "```\n"
227
+ manpage.print "\n"
227
228
  # output help for every unhidden command
228
229
  Morpheus::Cli::CliRegistry.all.keys.sort.each do |cmd|
229
230
  cmd_klass = Morpheus::Cli::CliRegistry.instance.get(cmd)
@@ -231,37 +232,37 @@ ENDTEXT
231
232
  Morpheus::Logging::DarkPrinter.puts "appending command help `morpheus #{cmd} --help`" if Morpheus::Logging.debug?
232
233
  #help_cmd = "morpheus #{cmd} --help"
233
234
  #help_output = `#{help_cmd}`
234
- $stdout.print "\n"
235
- $stdout.print "### morpheus #{cmd}\n"
236
- $stdout.print "\n"
237
- $stdout.print "```\n"
235
+ manpage.print "\n"
236
+ manpage.print "### morpheus #{cmd}\n"
237
+ manpage.print "\n"
238
+ manpage.print "```\n"
238
239
  begin
239
240
  cmd_instance.handle(["--help"])
240
241
  rescue SystemExit => err
241
242
  raise err unless err.success?
242
243
  end
243
- $stdout.print "```\n"
244
+ manpage.print "```\n"
244
245
  subcommands = cmd_klass.subcommands
245
246
  if subcommands && subcommands.size > 0
246
247
  subcommands.sort.each do |subcommand, subcommand_method|
247
248
  Morpheus::Logging::DarkPrinter.puts "appending command help `morpheus #{cmd} #{subcommand} --help`" if Morpheus::Logging.debug?
248
- $stdout.print "\n"
249
- $stdout.print "#### morpheus #{cmd} #{subcommand}\n"
250
- $stdout.print "\n"
251
- $stdout.print "```\n"
249
+ manpage.print "\n"
250
+ manpage.print "#### morpheus #{cmd} #{subcommand}\n"
251
+ manpage.print "\n"
252
+ manpage.print "```\n"
252
253
  begin
253
254
  cmd_instance.handle([subcommand, "--help"])
254
255
  rescue SystemExit => err
255
256
  raise err unless err.success?
256
257
  end
257
- $stdout.print "```\n"
258
- # $stdout.print "\n"
258
+ manpage.print "```\n"
259
+ # manpage.print "\n"
259
260
  end
260
261
  end
261
- $stdout.print "\n"
262
+ manpage.print "\n"
262
263
  end
263
264
 
264
- $stdout.print <<-ENDTEXT
265
+ manpage.print <<-ENDTEXT
265
266
 
266
267
  ## ENVIRONMENT VARIABLES
267
268
 
@@ -379,7 +380,9 @@ ENDTEXT
379
380
 
380
381
  ensure
381
382
  manpage.close if manpage
382
- $stdout = previous_stdout if previous_stdout
383
+ # $stdout = previous_stdout if previous_stdout
384
+ # this is needed to re-establish instance with STDOUT, STDIN
385
+ terminal = Morpheus::Terminal.new()
383
386
  end
384
387
 
385
388
  return true
@@ -24,6 +24,11 @@ module Morpheus::Cli::PrintHelper
24
24
  @@terminal_width
25
25
  end
26
26
 
27
+ # for consistancy, maybe..
28
+ unless defined?(ALL_LABELS_UPCASE)
29
+ ALL_LABELS_UPCASE = false
30
+ end
31
+
27
32
  def current_terminal_width
28
33
  return IO.console.winsize[1] rescue 0
29
34
  end
@@ -88,7 +93,7 @@ module Morpheus::Cli::PrintHelper
88
93
  end
89
94
  end
90
95
 
91
- def print_dry_run(opts)
96
+ def print_dry_run(opts, command_string=nil)
92
97
  http_method = opts[:method]
93
98
  url = opts[:url]
94
99
  params = opts[:params]
@@ -99,7 +104,11 @@ module Morpheus::Cli::PrintHelper
99
104
  end
100
105
  request_string = "#{http_method.to_s.upcase} #{url}".strip
101
106
  payload = opts[:payload]
102
- print_h1 "DRY RUN"
107
+ if command_string
108
+ print_h1 "DRY RUN > #{command_string}"
109
+ else
110
+ print_h1 "DRY RUN"
111
+ end
103
112
  print cyan
104
113
  print "Request: ", "\n"
105
114
  print reset
@@ -187,7 +196,7 @@ module Morpheus::Cli::PrintHelper
187
196
  # shows cyan, yellow, red progress bar where 50% looks like [||||| ]
188
197
  # todo: render units used / available here too maybe
189
198
  def generate_usage_bar(used_value, max_value, opts={})
190
- rainbow = opts[:rainbow] != false
199
+ opts[:bar_color] ||= :rainbow # :rainbow, :solid, or a color eg. cyan
191
200
  max_bars = opts[:max_bars] || 50
192
201
  out = ""
193
202
  bars = []
@@ -207,7 +216,7 @@ module Morpheus::Cli::PrintHelper
207
216
  n_bars.times { bars << "|" }
208
217
  end
209
218
 
210
- if rainbow
219
+ if opts[:bar_color] == :rainbow
211
220
  rainbow_bar = ""
212
221
  cur_rainbow_color = white
213
222
  bars.each_with_index {|bar, i|
@@ -234,7 +243,7 @@ module Morpheus::Cli::PrintHelper
234
243
  rainbow_bar << reset
235
244
  bar_display = white + "[" + rainbow_bar + white + "]" + " #{cur_rainbow_color}#{percent_label}#{reset}"
236
245
  out << bar_display
237
- else
246
+ elsif opts[:bar_color] == :solid
238
247
  bar_color = cyan
239
248
  if percent > 80
240
249
  bar_color = red
@@ -243,6 +252,10 @@ module Morpheus::Cli::PrintHelper
243
252
  end
244
253
  bar_display = white + "[" + bar_color + bars.join.ljust(max_bars, ' ') + white + "]" + " #{percent_label}" + reset
245
254
  out << bar_display
255
+ else
256
+ bar_color = opts[:bar_color] || cyan
257
+ bar_display = white + "[" + bar_color + bars.join.ljust(max_bars, ' ') + white + "]" + " #{percent_label}" + reset
258
+ out << bar_display
246
259
  end
247
260
  return out
248
261
  end
@@ -487,6 +500,7 @@ module Morpheus::Cli::PrintHelper
487
500
 
488
501
  columns.flatten.each do |column_def|
489
502
  label = column_def.label
503
+ label = label.upcase if ALL_LABELS_UPCASE
490
504
  # value = get_object_value(obj, column_def.display_method)
491
505
  value = column_def.display_method.call(obj)
492
506
  if label.size > max_label_width