morpheus-cli 2.10.3 → 2.11.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/bin/morpheus +5 -96
  3. data/lib/morpheus/api/api_client.rb +23 -1
  4. data/lib/morpheus/api/checks_interface.rb +106 -0
  5. data/lib/morpheus/api/incidents_interface.rb +102 -0
  6. data/lib/morpheus/api/monitoring_apps_interface.rb +47 -0
  7. data/lib/morpheus/api/monitoring_contacts_interface.rb +47 -0
  8. data/lib/morpheus/api/monitoring_groups_interface.rb +47 -0
  9. data/lib/morpheus/api/monitoring_interface.rb +36 -0
  10. data/lib/morpheus/api/option_type_lists_interface.rb +47 -0
  11. data/lib/morpheus/api/option_types_interface.rb +47 -0
  12. data/lib/morpheus/api/roles_interface.rb +0 -1
  13. data/lib/morpheus/api/setup_interface.rb +19 -9
  14. data/lib/morpheus/cli.rb +20 -1
  15. data/lib/morpheus/cli/accounts.rb +8 -3
  16. data/lib/morpheus/cli/app_templates.rb +19 -11
  17. data/lib/morpheus/cli/apps.rb +52 -37
  18. data/lib/morpheus/cli/cli_command.rb +229 -53
  19. data/lib/morpheus/cli/cli_registry.rb +48 -40
  20. data/lib/morpheus/cli/clouds.rb +55 -26
  21. data/lib/morpheus/cli/command_error.rb +12 -0
  22. data/lib/morpheus/cli/credentials.rb +68 -26
  23. data/lib/morpheus/cli/curl_command.rb +98 -0
  24. data/lib/morpheus/cli/dashboard_command.rb +2 -7
  25. data/lib/morpheus/cli/deployments.rb +4 -4
  26. data/lib/morpheus/cli/deploys.rb +1 -2
  27. data/lib/morpheus/cli/dot_file.rb +5 -8
  28. data/lib/morpheus/cli/error_handler.rb +179 -15
  29. data/lib/morpheus/cli/groups.rb +21 -13
  30. data/lib/morpheus/cli/hosts.rb +220 -110
  31. data/lib/morpheus/cli/instance_types.rb +2 -2
  32. data/lib/morpheus/cli/instances.rb +257 -167
  33. data/lib/morpheus/cli/key_pairs.rb +15 -9
  34. data/lib/morpheus/cli/library.rb +673 -27
  35. data/lib/morpheus/cli/license.rb +2 -2
  36. data/lib/morpheus/cli/load_balancers.rb +4 -4
  37. data/lib/morpheus/cli/log_level_command.rb +6 -4
  38. data/lib/morpheus/cli/login.rb +17 -3
  39. data/lib/morpheus/cli/logout.rb +25 -11
  40. data/lib/morpheus/cli/man_command.rb +388 -0
  41. data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -1
  42. data/lib/morpheus/cli/mixins/monitoring_helper.rb +434 -0
  43. data/lib/morpheus/cli/mixins/print_helper.rb +620 -112
  44. data/lib/morpheus/cli/mixins/provisioning_helper.rb +1 -1
  45. data/lib/morpheus/cli/monitoring_apps_command.rb +29 -0
  46. data/lib/morpheus/cli/monitoring_checks_command.rb +427 -0
  47. data/lib/morpheus/cli/monitoring_contacts_command.rb +373 -0
  48. data/lib/morpheus/cli/monitoring_groups_command.rb +29 -0
  49. data/lib/morpheus/cli/monitoring_incidents_command.rb +711 -0
  50. data/lib/morpheus/cli/option_types.rb +10 -1
  51. data/lib/morpheus/cli/recent_activity_command.rb +2 -5
  52. data/lib/morpheus/cli/remote.rb +874 -134
  53. data/lib/morpheus/cli/roles.rb +54 -27
  54. data/lib/morpheus/cli/security_group_rules.rb +2 -2
  55. data/lib/morpheus/cli/security_groups.rb +23 -19
  56. data/lib/morpheus/cli/set_prompt_command.rb +50 -0
  57. data/lib/morpheus/cli/shell.rb +222 -157
  58. data/lib/morpheus/cli/tasks.rb +19 -15
  59. data/lib/morpheus/cli/users.rb +27 -17
  60. data/lib/morpheus/cli/version.rb +1 -1
  61. data/lib/morpheus/cli/virtual_images.rb +28 -13
  62. data/lib/morpheus/cli/whoami.rb +131 -52
  63. data/lib/morpheus/cli/workflows.rb +24 -9
  64. data/lib/morpheus/formatters.rb +195 -3
  65. data/lib/morpheus/logging.rb +86 -0
  66. data/lib/morpheus/terminal.rb +371 -0
  67. data/scripts/generate_morpheus_commands_help.morpheus +60 -0
  68. metadata +21 -2
@@ -52,7 +52,7 @@ class Morpheus::Cli::InstanceTypes
52
52
  if instance_type.nil?
53
53
  puts yellow,"No instance type found by name #{name}.",reset
54
54
  else
55
- print "\n" ,cyan, bold, "Instance Type Details\n","==================", reset, "\n\n"
55
+ print_h1 "Instance Type Details"
56
56
  versions = instance_type['versions'].join(', ')
57
57
  print cyan, "= #{instance_type['name']} (#{instance_type['code']}) - #{versions}\n"
58
58
  layout_names = instance_type['instanceTypeLayouts'].collect { |layout| layout['name'] }.uniq.sort
@@ -97,7 +97,7 @@ class Morpheus::Cli::InstanceTypes
97
97
  end
98
98
 
99
99
  instance_types = json_response['instanceTypes']
100
- print "\n" ,cyan, bold, "Morpheus Instance Types\n","==================", reset, "\n\n"
100
+ print_h1 "Morpheus Instance Types"
101
101
  if instance_types.empty?
102
102
  puts yellow,"No instance types currently configured.",reset
103
103
  else
@@ -11,7 +11,7 @@ class Morpheus::Cli::Instances
11
11
  include Morpheus::Cli::CliCommand
12
12
  include Morpheus::Cli::ProvisioningHelper
13
13
 
14
- register_subcommands :list, :get, :add, :update, :remove, :stats, :stop, :start, :restart, :suspend, :eject, :backup, :backups, :stop_service, :start_service, :restart_service, :resize, :clone, :envs, :setenv, :delenv, :security_groups, :apply_security_groups, :firewall_enable, :firewall_disable, :run_workflow, :import_snapshot, :console, :status_check
14
+ register_subcommands :list, :get, :add, :update, :remove, :logs, :stats, :stop, :start, :restart, :suspend, :eject, :backup, :backups, :stop_service, :start_service, :restart_service, :resize, :clone, :envs, :setenv, :delenv, :security_groups, :apply_security_groups, :firewall_enable, :firewall_disable, :run_workflow, :import_snapshot, :console, :status_check
15
15
  alias_subcommand :details, :get
16
16
  set_default_subcommand :list
17
17
 
@@ -83,8 +83,7 @@ class Morpheus::Cli::Instances
83
83
  end
84
84
  json_response = @instances_interface.create(payload)
85
85
  if options[:json]
86
- print JSON.pretty_generate(json_response)
87
- print "\n"
86
+ puts as_json(json_response, options)
88
87
  else
89
88
  instance_name = json_response["instance"]["name"]
90
89
  print_green_success "Provisioning instance #{instance_name}"
@@ -145,8 +144,7 @@ class Morpheus::Cli::Instances
145
144
  json_response = @instances_interface.update(instance["id"], payload)
146
145
 
147
146
  if options[:json]
148
- print JSON.pretty_generate(json_response)
149
- print "\n"
147
+ puts as_json(json_response, options)
150
148
  else
151
149
  print_green_success "Updated instance #{instance['name']}"
152
150
  list([])
@@ -179,7 +177,7 @@ class Morpheus::Cli::Instances
179
177
  end
180
178
  if options[:json]
181
179
  mock_json = {status: instance['status'], exit: exit_code}
182
- out << JSON.pretty_generate(mock_json)
180
+ out << as_json(mock_json, options)
183
181
  out << "\n"
184
182
  elsif !options[:quiet]
185
183
  out << cyan
@@ -195,7 +193,7 @@ class Morpheus::Cli::Instances
195
193
  options = {}
196
194
  optparse = OptionParser.new do|opts|
197
195
  opts.banner = subcommand_usage("[name]")
198
- build_common_options(opts, options, [:json, :dry_run, :remote])
196
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
199
197
  end
200
198
  optparse.parse!(args)
201
199
  if args.count < 1
@@ -203,33 +201,40 @@ class Morpheus::Cli::Instances
203
201
  exit 1
204
202
  end
205
203
  connect(options)
204
+ ids = args
205
+ id_list = parse_id_list(args)
206
+ return run_command_for_each_arg(id_list) do |arg|
207
+ _stats(arg, options)
208
+ end
209
+ end
210
+
211
+ def _stats(arg, options)
206
212
  begin
207
- instance = find_instance_by_name_or_id(args[0])
213
+ instance = find_instance_by_name_or_id(arg)
208
214
  if options[:dry_run]
209
215
  print_dry_run @instances_interface.dry.get(instance['id'])
210
- return
216
+ return 0
211
217
  end
212
218
  json_response = @instances_interface.get(instance['id'])
213
219
  if options[:json]
214
- print JSON.pretty_generate(json_response), "\n"
215
- return
220
+ puts as_json(json_response, options)
221
+ return 0
222
+ elsif options[:yaml]
223
+ if options[:include_fields]
224
+ json_response = {"stats" => filter_data(json_response["stats"], options[:include_fields]) }
225
+ end
226
+ puts as_yaml(json_response, options)
227
+ return 0
216
228
  end
217
229
  instance = json_response['instance']
218
230
  stats = json_response['stats'] || {}
219
- print "\n" ,cyan, bold, "Instance Stats: #{instance['name']} (#{instance['instanceType']['name']})\n","==================", "\n\n", reset, cyan
220
- puts "Status: #{format_instance_status(instance)}"
221
- print "\n"
222
- if ((stats['maxMemory'].to_i != 0) || (stats['maxStorage'].to_i != 0))
223
- # stats_map = {}
224
- # stats_map[:memory] = "#{Filesize.from("#{stats['usedMemory']} B").pretty} / #{Filesize.from("#{stats['maxMemory']} B").pretty}"
225
- # stats_map[:storage] = "#{Filesize.from("#{stats['usedStorage']} B").pretty} / #{Filesize.from("#{stats['maxStorage']} B").pretty}"
226
- # stats_map[:cpu] = "#{stats['usedCpu'].to_f.round(2)}%"
227
- # tp [stats_map], :memory,:storage,:cpu
228
- # print "\n"
229
- print_stats_usage(stats)
230
- else
231
- print cyan, "No data.", "\n", reset
232
- end
231
+ title = "Instance Stats: #{instance['name']} (#{instance['instanceType']['name']})"
232
+ print_h1 title
233
+ puts cyan + "Status: ".rjust(12) + format_instance_status(instance).to_s
234
+ puts cyan + "Nodes: ".rjust(12) + (instance['containers'] ? instance['containers'].count : '').to_s
235
+ # print "\n"
236
+ #print_h2 "Instance Usage"
237
+ print_stats_usage(stats)
233
238
  print reset, "\n"
234
239
  rescue RestClient::Exception => e
235
240
  print_rest_exception(e, options)
@@ -281,7 +286,7 @@ class Morpheus::Cli::Instances
281
286
  opts.on( '-n', '--node NODE_ID', "Scope logs to specific Container or VM" ) do |node_id|
282
287
  options[:node_id] = node_id.to_i
283
288
  end
284
- build_common_options(opts, options, [:list, :json, :dry_run, :remote])
289
+ build_common_options(opts, options, [:list, :json, :csv, :dry_run, :remote])
285
290
  end
286
291
  optparse.parse!(args)
287
292
  if args.count < 1
@@ -295,32 +300,52 @@ class Morpheus::Cli::Instances
295
300
  if options[:node_id] && container_ids.include?(options[:node_id])
296
301
  container_ids = [options[:node_id]]
297
302
  end
298
- query_params = { max: options[:max] || 100, offset: options[:offset] || 0, query: options[:phrase]}
303
+ params = {}
304
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
305
+ params[k] = options[k] unless options[k].nil?
306
+ end
307
+ params[:query] = params.delete(:phrase) unless params[:phrase].nil?
299
308
  if options[:dry_run]
300
- print_dry_run @logs_interface.dry.container_logs(container_ids, query_params)
309
+ print_dry_run @logs_interface.dry.server_logs([server['id']], params)
301
310
  return
302
311
  end
303
- logs = @logs_interface.container_logs(container_ids, query_params)
312
+ if options[:dry_run]
313
+ print_dry_run @logs_interface.dry.container_logs(container_ids, params)
314
+ return
315
+ end
316
+ logs = @logs_interface.container_logs(container_ids, params)
317
+ output = ""
304
318
  if options[:json]
305
- puts logs
319
+ output << as_json(logs, options)
306
320
  else
307
- logs['data'].reverse.each do |log_entry|
308
- log_level = ''
309
- case log_entry['level']
310
- when 'INFO'
311
- log_level = "#{blue}#{bold}INFO#{reset}"
312
- when 'DEBUG'
313
- log_level = "#{white}#{bold}DEBUG#{reset}"
314
- when 'WARN'
315
- log_level = "#{yellow}#{bold}WARN#{reset}"
316
- when 'ERROR'
317
- log_level = "#{red}#{bold}ERROR#{reset}"
318
- when 'FATAL'
319
- log_level = "#{red}#{bold}FATAL#{reset}"
321
+ title = "Instance Logs: #{instance['name']} (#{instance['instanceType'] ? instance['instanceType']['name'] : ''})"
322
+ subtitles = []
323
+ if params[:query]
324
+ subtitles << "Search: #{params[:query]}".strip
325
+ end
326
+ # todo: startMs, endMs, sorts insteaad of sort..etc
327
+ print_h1 title, subtitles
328
+ if logs['data'].empty?
329
+ output << "#{cyan}No logs found.#{reset}\n"
330
+ else
331
+ logs['data'].reverse.each do |log_entry|
332
+ log_level = ''
333
+ case log_entry['level']
334
+ when 'INFO'
335
+ log_level = "#{blue}#{bold}INFO#{reset}"
336
+ when 'DEBUG'
337
+ log_level = "#{white}#{bold}DEBUG#{reset}"
338
+ when 'WARN'
339
+ log_level = "#{yellow}#{bold}WARN#{reset}"
340
+ when 'ERROR'
341
+ log_level = "#{red}#{bold}ERROR#{reset}"
342
+ when 'FATAL'
343
+ log_level = "#{red}#{bold}FATAL#{reset}"
344
+ end
345
+ output << "[#{log_entry['ts']}] #{log_level} - #{log_entry['message']}\n"
320
346
  end
321
- puts "[#{log_entry['ts']}] #{log_level} - #{log_entry['message']}"
322
347
  end
323
- print reset,"\n"
348
+ print output, reset, "\n"
324
349
  end
325
350
  rescue RestClient::Exception => e
326
351
  print_rest_exception(e, options)
@@ -332,7 +357,7 @@ class Morpheus::Cli::Instances
332
357
  options = {}
333
358
  optparse = OptionParser.new do|opts|
334
359
  opts.banner = subcommand_usage("[name]")
335
- build_common_options(opts, options, [:json, :dry_run, :remote])
360
+ build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
336
361
  end
337
362
  optparse.parse!(args)
338
363
  if args.count < 1
@@ -340,54 +365,67 @@ class Morpheus::Cli::Instances
340
365
  exit 1
341
366
  end
342
367
  connect(options)
368
+ id_list = parse_id_list(args)
369
+ return run_command_for_each_arg(id_list) do |arg|
370
+ _get(arg, options)
371
+ end
372
+ end
373
+
374
+ def _get(arg, options)
343
375
  begin
344
376
  if options[:dry_run]
345
- if args[0].to_s =~ /\A\d{1,}\Z/
346
- print_dry_run @instances_interface.dry.get(args[0].to_i)
377
+ if arg.to_s =~ /\A\d{1,}\Z/
378
+ print_dry_run @instances_interface.dry.get(arg.to_i)
347
379
  else
348
- print_dry_run @instances_interface.dry.get({name:args[0]})
380
+ print_dry_run @instances_interface.dry.get({name:arg})
349
381
  end
350
382
  return
351
383
  end
352
- instance = find_instance_by_name_or_id(args[0])
384
+ instance = find_instance_by_name_or_id(arg)
353
385
  json_response = @instances_interface.get(instance['id'])
354
386
  if options[:json]
355
- print JSON.pretty_generate(json_response), "\n"
356
- return
387
+ if options[:include_fields]
388
+ json_response = {"instance" => filter_data(json_response["instance"], options[:include_fields]) }
389
+ end
390
+ puts as_json(json_response, options)
391
+ return 0
392
+ elsif options[:yaml]
393
+ if options[:include_fields]
394
+ json_response = {"instance" => filter_data(json_response["instance"], options[:include_fields]) }
395
+ end
396
+ puts as_yaml(json_response, options)
397
+ return 0
398
+ end
399
+
400
+ if options[:csv]
401
+ puts records_as_csv([json_response['instance']], options)
402
+ return 0
357
403
  end
358
404
  instance = json_response['instance']
359
405
  stats = json_response['stats'] || {}
360
406
  # load_balancers = stats = json_response['loadBalancers'] || {}
361
407
 
362
- connection_string = ''
363
- if !instance['connectionInfo'].nil? && instance['connectionInfo'].empty? == false
364
- connection_string = "#{instance['connectionInfo'][0]['ip']}:#{instance['connectionInfo'][0]['port']}"
365
- end
366
-
367
- print "\n" ,cyan, bold, "Instance Details\n","==================", reset, "\n\n"
408
+ print_h1 "Instance Details"
368
409
  print cyan
369
- puts "ID: #{instance['id']}"
370
- puts "Name: #{instance['name']}"
371
- puts "Description: #{instance['description']}"
372
- puts "Group: #{instance['group'] ? instance['group']['name'] : ''}"
373
- puts "Cloud: #{instance['cloud'] ? instance['cloud']['name'] : ''}"
374
- puts "Type: #{instance['instanceType']['name']}"
375
- puts "Plan: #{instance['plan'] ? instance['plan']['name'] : ''}"
376
- puts "Environment: #{instance['instanceContext']}"
377
- puts "Nodes: #{instance['containers'] ? instance['containers'].count : 0}"
378
- puts "Connection: #{connection_string}"
379
- #puts "Account: #{instance['account'] ? instance['account']['name'] : ''}"
380
- puts "Status: #{format_instance_status(instance)}"
381
- if ((stats['maxMemory'].to_i != 0) || (stats['maxStorage'].to_i != 0))
382
- print "\n"
383
- # stats_map = {}
384
- # stats_map[:memory] = "#{Filesize.from("#{stats['usedMemory']} B").pretty} / #{Filesize.from("#{stats['maxMemory']} B").pretty}"
385
- # stats_map[:storage] = "#{Filesize.from("#{stats['usedStorage']} B").pretty} / #{Filesize.from("#{stats['maxStorage']} B").pretty}"
386
- # stats_map[:cpu] = "#{stats['usedCpu'].to_f.round(2)}%"
387
- # tp [stats_map], :memory,:storage,:cpu
410
+ description_cols = {
411
+ "ID" => 'id',
412
+ "Name" => 'name',
413
+ "Description" => 'description',
414
+ "Group" => lambda {|it| it['group'] ? it['group']['name'] : '' },
415
+ "Cloud" => lambda {|it| it['cloud'] ? it['cloud']['name'] : '' },
416
+ "Type" => lambda {|it| it['instanceType']['name'] },
417
+ "Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
418
+ "Environment" => 'instanceContext',
419
+ "Nodes" => lambda {|it| it['containers'] ? it['containers'].count : 0 },
420
+ "Connection" => lambda {|it| format_instance_connection_string(it) },
421
+ #"Account" => lambda {|it| it['account'] ? it['account']['name'] : '' },
422
+ "Status" => lambda {|it| format_instance_status(it) }
423
+ }
424
+ print_description_list(description_cols, instance)
425
+
426
+ if (stats)
427
+ print_h2 "Instance Usage"
388
428
  print_stats_usage(stats)
389
- else
390
- # print cyan, "No data.", "\n", reset
391
429
  end
392
430
  print reset, "\n"
393
431
 
@@ -419,19 +457,14 @@ class Morpheus::Cli::Instances
419
457
  end
420
458
  json_response = @instances_interface.backups(instance['id'], params)
421
459
  if options[:json]
422
- print JSON.pretty_generate(json_response), "\n"
460
+ puts as_json(json_response, options)
423
461
  return
424
462
  end
425
463
  backups = json_response['backups']
426
464
  stats = json_response['stats'] || {}
427
465
  # load_balancers = stats = json_response['loadBalancers'] || {}
428
466
 
429
- print "\n" ,cyan, bold, "Instance Backups\n","==================", reset, "\n\n"
430
- print cyan
431
- puts "ID: #{instance['id']}"
432
- puts "Name: #{instance['name']}"
433
- print "\n"
434
- puts "Backups:"
467
+ print_h1 "Instance Backups: #{instance['name']} (#{instance['instanceType']['name']})"
435
468
  backup_rows = backups.collect {|it| {id: it['id'], name: it['name'], dateCreated: it['dateCreated']} }
436
469
  print cyan
437
470
  tp backup_rows, [
@@ -494,8 +527,7 @@ class Morpheus::Cli::Instances
494
527
  end
495
528
  json_response = @instances_interface.clone(instance['id'], payload)
496
529
  if options[:json]
497
- print JSON.pretty_generate(json_response)
498
- print "\n"
530
+ puts as_json(json_response, options)
499
531
  else
500
532
  print_green_success "Cloning instance #{instance['name']} to '#{payload['name']}'"
501
533
  end
@@ -527,16 +559,17 @@ class Morpheus::Cli::Instances
527
559
  end
528
560
  json_response = @instances_interface.get_envs(instance['id'])
529
561
  if options[:json]
530
- print JSON.pretty_generate(json_response), "\n"
562
+ puts as_json(json_response, options)
531
563
  return
532
564
  end
533
- print "\n" ,cyan, bold, "#{instance['name']} (#{instance['instanceType']['name']})\n","==================", "\n\n", reset, cyan
565
+ print_h1 "Instance Envs: #{instance['name']} (#{instance['instanceType']['name']})"
566
+ print cyan
534
567
  envs = json_response['envs'] || {}
535
568
  if json_response['readOnlyEnvs']
536
569
  envs += json_response['readOnlyEnvs'].map { |k,v| {:name => k, :value => k.downcase.include?("password") || v['masked'] ? "********" : v['value'], :export => true}}
537
570
  end
538
571
  tp envs, :name, :value, :export
539
- print "\n" ,cyan, bold, "Imported Envs\n","==================", "\n\n", reset, cyan
572
+ print_h2 "Imported Envs"
540
573
  imported_envs = json_response['importedEnvs'].map { |k,v| {:name => k, :value => k.downcase.include?("password") || v['masked'] ? "********" : v['value']}}
541
574
  tp imported_envs
542
575
  print reset, "\n"
@@ -575,7 +608,7 @@ class Morpheus::Cli::Instances
575
608
  end
576
609
  json_response = @instances_interface.create_env(instance['id'], payload)
577
610
  if options[:json]
578
- print JSON.pretty_generate(json_response), "\n"
611
+ puts as_json(json_response, options)
579
612
  return
580
613
  end
581
614
  if !options[:quiet]
@@ -607,7 +640,7 @@ class Morpheus::Cli::Instances
607
640
  end
608
641
  json_response = @instances_interface.del_env(instance['id'], args[1])
609
642
  if options[:json]
610
- print JSON.pretty_generate(json_response), "\n"
643
+ puts as_json(json_response, options)
611
644
  return
612
645
  end
613
646
  if !options[:quiet]
@@ -642,7 +675,7 @@ class Morpheus::Cli::Instances
642
675
  end
643
676
  json_response = @instances_interface.stop(instance['id'])
644
677
  if options[:json]
645
- print JSON.pretty_generate(json_response)
678
+ puts as_json(json_response, options)
646
679
  print "\n"
647
680
  end
648
681
  return
@@ -672,8 +705,8 @@ class Morpheus::Cli::Instances
672
705
  end
673
706
  json_response = @instances_interface.start(instance['id'])
674
707
  if options[:json]
675
- print JSON.pretty_generate(json_response)
676
- print "\n"
708
+ puts as_json(json_response, options)
709
+ return 0
677
710
  end
678
711
  return
679
712
  rescue RestClient::Exception => e
@@ -705,8 +738,7 @@ class Morpheus::Cli::Instances
705
738
  end
706
739
  json_response = @instances_interface.restart(instance['id'])
707
740
  if options[:json]
708
- print JSON.pretty_generate(json_response)
709
- print "\n"
741
+ puts as_json(json_response, options)
710
742
  end
711
743
  return
712
744
  rescue RestClient::Exception => e
@@ -738,10 +770,9 @@ class Morpheus::Cli::Instances
738
770
  end
739
771
  json_response = @instances_interface.suspend(instance['id'])
740
772
  if options[:json]
741
- print JSON.pretty_generate(json_response)
742
- print "\n"
773
+ puts as_json(json_response, options)
743
774
  end
744
- return
775
+ return 0
745
776
  rescue RestClient::Exception => e
746
777
  print_rest_exception(e, options)
747
778
  exit 1
@@ -771,10 +802,9 @@ class Morpheus::Cli::Instances
771
802
  end
772
803
  json_response = @instances_interface.eject(instance['id'])
773
804
  if options[:json]
774
- print JSON.pretty_generate(json_response)
775
- print "\n"
805
+ puts as_json(json_response, options)
776
806
  end
777
- return
807
+ return 0
778
808
  rescue RestClient::Exception => e
779
809
  print_rest_exception(e, options)
780
810
  exit 1
@@ -804,12 +834,11 @@ class Morpheus::Cli::Instances
804
834
  end
805
835
  json_response = @instances_interface.stop(instance['id'],false)
806
836
  if options[:json]
807
- print JSON.pretty_generate(json_response)
808
- print "\n"
837
+ puts as_json(json_response, options)
809
838
  else
810
839
  puts "Stopping service on #{args[0]}"
811
840
  end
812
- return
841
+ return 0
813
842
  rescue RestClient::Exception => e
814
843
  print_rest_exception(e, options)
815
844
  exit 1
@@ -836,12 +865,11 @@ class Morpheus::Cli::Instances
836
865
  end
837
866
  json_response = @instances_interface.start(instance['id'],false)
838
867
  if options[:json]
839
- print JSON.pretty_generate(json_response)
840
- print "\n"
868
+ puts as_json(json_response, options)
841
869
  else
842
870
  puts "Starting service on #{args[0]}"
843
871
  end
844
- return
872
+ return 0
845
873
  rescue RestClient::Exception => e
846
874
  print_rest_exception(e, options)
847
875
  exit 1
@@ -871,8 +899,7 @@ class Morpheus::Cli::Instances
871
899
  end
872
900
  json_response = @instances_interface.restart(instance['id'],false)
873
901
  if options[:json]
874
- print JSON.pretty_generate(json_response)
875
- print "\n"
902
+ puts as_json(json_response, options)
876
903
  else
877
904
  puts "Restarting service on instance #{args[0]}"
878
905
  end
@@ -947,8 +974,8 @@ class Morpheus::Cli::Instances
947
974
  end
948
975
  json_response = @instances_interface.resize(instance['id'], payload)
949
976
  if options[:json]
950
- print JSON.pretty_generate(json_response)
951
- print "\n"
977
+ puts as_json(json_response, options)
978
+ return 0
952
979
  else
953
980
  print_green_success "Resizing instance #{instance['name']}"
954
981
  list([])
@@ -982,12 +1009,12 @@ class Morpheus::Cli::Instances
982
1009
  end
983
1010
  json_response = @instances_interface.backup(instance['id'])
984
1011
  if options[:json]
985
- print JSON.pretty_generate(json_response)
986
- print "\n"
1012
+ puts as_json(json_response, options)
1013
+ return 0
987
1014
  else
988
1015
  puts "Backup initiated."
1016
+ return 0
989
1017
  end
990
- return
991
1018
  rescue RestClient::Exception => e
992
1019
  print_rest_exception(e, options)
993
1020
  exit 1
@@ -1004,7 +1031,7 @@ class Morpheus::Cli::Instances
1004
1031
  opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
1005
1032
  options[:cloud] = val
1006
1033
  end
1007
- build_common_options(opts, options, [:list, :json, :dry_run, :remote])
1034
+ build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :dry_run, :remote])
1008
1035
  end
1009
1036
  optparse.parse!(args)
1010
1037
  connect(options)
@@ -1032,8 +1059,26 @@ class Morpheus::Cli::Instances
1032
1059
  end
1033
1060
  json_response = @instances_interface.get(params)
1034
1061
  if options[:json]
1035
- print JSON.pretty_generate(json_response)
1036
- print "\n"
1062
+ if options[:include_fields]
1063
+ json_response = {"instances" => filter_data(json_response["instances"], options[:include_fields]) }
1064
+ end
1065
+ puts as_json(json_response, options)
1066
+ return 0
1067
+ elsif options[:yaml]
1068
+ if options[:include_fields]
1069
+ json_response = {"instances" => filter_data(json_response["instances"], options[:include_fields]) }
1070
+ end
1071
+ puts as_yaml(json_response, options)
1072
+ return 0
1073
+ elsif options[:csv]
1074
+ # merge stats to be nice here..
1075
+ if json_response['instances']
1076
+ all_stats = json_response['stats'] || {}
1077
+ json_response['instances'].each do |it|
1078
+ it['stats'] ||= all_stats[it['id'].to_s] || all_stats[it['id']]
1079
+ end
1080
+ end
1081
+ puts records_as_csv(json_response['instances'], options)
1037
1082
  else
1038
1083
  instances = json_response['instances']
1039
1084
 
@@ -1048,12 +1093,55 @@ class Morpheus::Cli::Instances
1048
1093
  if params[:phrase]
1049
1094
  subtitles << "Search: #{params[:phrase]}".strip
1050
1095
  end
1051
- subtitle = subtitles.join(', ')
1052
- print "\n" ,cyan, bold, title, (subtitle.empty? ? "" : " - #{subtitle}"), "\n", "==================", reset, "\n\n"
1096
+ print_h1 title, subtitles
1053
1097
  if instances.empty?
1054
- puts yellow,"No instances found.",reset
1098
+ print yellow,"No instances found.",reset,"\n"
1055
1099
  else
1056
- print_instances_table(instances)
1100
+ # print_instances_table(instances)
1101
+ # server returns stats in a separate key stats => {"id" => {} }
1102
+ # the id is a string right now..for some reason..
1103
+ all_stats = json_response['stats'] || {}
1104
+ instances.each do |it|
1105
+ if !it['stats']
1106
+ found_stats = all_stats[it['id'].to_s] || all_stats[it['id']]
1107
+ it['stats'] = found_stats # || {}
1108
+ end
1109
+ end
1110
+
1111
+ rows = instances.collect {|instance|
1112
+ stats = instance['stats']
1113
+ cpu_usage_str = !stats ? "" : generate_usage_bar((stats['usedCpu'] || stats['cpuUsage']).to_f, 100, {max_bars: 10})
1114
+ memory_usage_str = !stats ? "" : generate_usage_bar(stats['usedMemory'], stats['maxMemory'], {max_bars: 10})
1115
+ storage_usage_str = !stats ? "" : generate_usage_bar(stats['usedStorage'], stats['maxStorage'], {max_bars: 10})
1116
+ row = {
1117
+ id: instance['id'],
1118
+ name: instance['name'],
1119
+ connection: format_instance_connection_string(instance),
1120
+ environment: instance['instanceContext'],
1121
+ nodes: instance['containers'].count,
1122
+ status: format_instance_status(instance, cyan),
1123
+ type: instance['instanceType']['name'],
1124
+ group: !instance['group'].nil? ? instance['group']['name'] : nil,
1125
+ cloud: !instance['cloud'].nil? ? instance['cloud']['name'] : nil,
1126
+ version: instance['instanceVersion'] ? instance['instanceVersion'] : '',
1127
+ cpu: cpu_usage_str + cyan,
1128
+ memory: memory_usage_str + cyan,
1129
+ storage: storage_usage_str + cyan
1130
+ }
1131
+ row
1132
+ }
1133
+ columns = [:id, :name, :group, :cloud, :type, :version, :environment, :nodes, {:connection => {max_width: 20}}, :status]
1134
+ term_width = current_terminal_width()
1135
+ if term_width > 190
1136
+ columns += [:cpu, :memory, :storage]
1137
+ end
1138
+ # custom pretty table columns ...
1139
+ if options[:include_fields]
1140
+ columns = options[:include_fields]
1141
+ end
1142
+ print cyan
1143
+ print as_pretty_table(rows, columns, options)
1144
+ print reset
1057
1145
  print_results_pagination(json_response)
1058
1146
  end
1059
1147
  print reset,"\n"
@@ -1095,8 +1183,8 @@ class Morpheus::Cli::Instances
1095
1183
  end
1096
1184
  json_response = @instances_interface.destroy(instance['id'],query_params)
1097
1185
  if options[:json]
1098
- print JSON.pretty_generate(json_response)
1099
- print "\n"
1186
+ print as_json(json_response, options), "\n"
1187
+ return
1100
1188
  elsif !options[:quiet]
1101
1189
  list([])
1102
1190
  end
@@ -1126,8 +1214,8 @@ class Morpheus::Cli::Instances
1126
1214
  end
1127
1215
  json_response = @instances_interface.firewall_disable(instance['id'])
1128
1216
  if options[:json]
1129
- print JSON.pretty_generate(json_response)
1130
- print "\n"
1217
+ print as_json(json_response, options), "\n"
1218
+ return
1131
1219
  elsif !options[:quiet]
1132
1220
  security_groups([args[0]])
1133
1221
  end
@@ -1157,8 +1245,8 @@ class Morpheus::Cli::Instances
1157
1245
  end
1158
1246
  json_response = @instances_interface.firewall_enable(instance['id'])
1159
1247
  if options[:json]
1160
- print JSON.pretty_generate(json_response)
1161
- print "\n"
1248
+ print as_json(json_response, options), "\n"
1249
+ return
1162
1250
  elsif !options[:quiet]
1163
1251
  security_groups([args[0]])
1164
1252
  end
@@ -1188,21 +1276,24 @@ class Morpheus::Cli::Instances
1188
1276
  end
1189
1277
  json_response = @instances_interface.security_groups(instance['id'])
1190
1278
  if options[:json]
1191
- print JSON.pretty_generate(json_response)
1192
- print "\n"
1279
+ print as_json(json_response, options), "\n"
1193
1280
  return
1194
1281
  end
1195
1282
  securityGroups = json_response['securityGroups']
1196
- print "\n" ,cyan, bold, "Morpheus Security Groups for Instance: #{instance['name']}\n","==================", reset, "\n\n"
1197
- print cyan, "Firewall Enabled=#{json_response['firewallEnabled']}\n\n"
1283
+ print_h1 "Morpheus Security Groups for Instance: #{instance['name']}"
1284
+ print cyan
1285
+ print_description_list({"Firewall Enabled" => lambda {|it| format_boolean it['firewallEnabled'] } }, json_response)
1286
+ #print cyan, "Firewall Enabled=#{json_response['firewallEnabled']}\n\n"
1198
1287
  if securityGroups.empty?
1199
- puts yellow,"No security groups currently applied.",reset
1288
+ print yellow,"\n","No security groups currently applied.",reset,"\n"
1200
1289
  else
1290
+ print "\n"
1201
1291
  securityGroups.each do |securityGroup|
1202
1292
  print cyan, "= #{securityGroup['id']} (#{securityGroup['name']}) - (#{securityGroup['description']})\n"
1203
1293
  end
1294
+ print "\n"
1204
1295
  end
1205
- print reset,"\n"
1296
+ print reset, "\n"
1206
1297
 
1207
1298
  rescue RestClient::Exception => e
1208
1299
  print_rest_exception(e, options)
@@ -1245,8 +1336,7 @@ class Morpheus::Cli::Instances
1245
1336
  end
1246
1337
  json_response = @instances_interface.apply_security_groups(instance['id'], payload)
1247
1338
  if options[:json]
1248
- print JSON.pretty_generate(json_response)
1249
- print "\n"
1339
+ print as_json(json_response, options), "\n"
1250
1340
  return
1251
1341
  end
1252
1342
  if !options[:quiet]
@@ -1303,8 +1393,8 @@ class Morpheus::Cli::Instances
1303
1393
  end
1304
1394
  json_response = @instances_interface.workflow(instance['id'],workflow['id'], workflow_payload)
1305
1395
  if options[:json]
1306
- print JSON.pretty_generate(json_response)
1307
- print "\n"
1396
+ print as_json(json_response, options), "\n"
1397
+ return
1308
1398
  else
1309
1399
  puts "Running workflow..."
1310
1400
  end
@@ -1358,12 +1448,11 @@ class Morpheus::Cli::Instances
1358
1448
  end
1359
1449
  json_response = @instances_interface.import_snapshot(instance['id'], payload)
1360
1450
  if options[:json]
1361
- print JSON.pretty_generate(json_response)
1362
- print "\n"
1451
+ puts as_json(json_response, options)
1363
1452
  else
1364
1453
  puts "Snapshot import initiated."
1365
1454
  end
1366
- return
1455
+ return 0
1367
1456
  rescue RestClient::Exception => e
1368
1457
  print_rest_exception(e, options)
1369
1458
  exit 1
@@ -1405,30 +1494,25 @@ class Morpheus::Cli::Instances
1405
1494
  end
1406
1495
  end
1407
1496
 
1408
- def print_instances_table(instances, opts={})
1409
- table_color = opts[:color] || cyan
1410
- rows = instances.collect do |instance|
1411
- connection_string = ''
1412
- if !instance['connectionInfo'].nil? && instance['connectionInfo'].empty? == false
1413
- connection_string = "#{instance['connectionInfo'][0]['ip']}:#{instance['connectionInfo'][0]['port']}"
1414
- end
1415
- {
1416
- id: instance['id'],
1417
- name: instance['name'],
1418
- connection: connection_string,
1419
- environment: instance['instanceContext'],
1420
- nodes: instance['containers'].count,
1421
- status: format_instance_status(instance, table_color),
1422
- type: instance['instanceType']['name'],
1423
- group: !instance['group'].nil? ? instance['group']['name'] : nil,
1424
- cloud: !instance['cloud'].nil? ? instance['cloud']['name'] : nil
1425
- }
1426
- end
1427
-
1428
- print table_color
1429
- tp rows, :id, :name, :group, :cloud, :type, :environment, :nodes, :connection, :status
1430
- print reset
1431
- end
1497
+ # def print_instances_table(instances, opts={})
1498
+ # table_color = opts[:color] || cyan
1499
+ # rows = instances.collect {|instance|
1500
+ # {
1501
+ # id: instance['id'],
1502
+ # name: instance['name'],
1503
+ # connection: format_instance_connection_string(instance),
1504
+ # environment: instance['instanceContext'],
1505
+ # nodes: instance['containers'].count,
1506
+ # status: format_instance_status(instance, table_color),
1507
+ # type: instance['instanceType']['name'],
1508
+ # group: !instance['group'].nil? ? instance['group']['name'] : nil,
1509
+ # cloud: !instance['cloud'].nil? ? instance['cloud']['name'] : nil
1510
+ # }
1511
+ # }
1512
+ # print table_color
1513
+ # tp rows, :id, :name, :group, :cloud, :type, :environment, :nodes, :connection, :status
1514
+ # print reset
1515
+ # end
1432
1516
 
1433
1517
  def format_instance_status(instance, return_color=cyan)
1434
1518
  out = ""
@@ -1445,6 +1529,12 @@ class Morpheus::Cli::Instances
1445
1529
  out
1446
1530
  end
1447
1531
 
1532
+ def format_instance_connection_string(instance)
1533
+ if !instance['connectionInfo'].nil? && instance['connectionInfo'].empty? == false
1534
+ connection_string = "#{instance['connectionInfo'][0]['ip']}:#{instance['connectionInfo'][0]['port']}"
1535
+ end
1536
+ end
1537
+
1448
1538
  def clone_instance_option_types(connected=true)
1449
1539
  [
1450
1540
  {'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Enter a name for the new instance'},