morpheus-cli 4.2.21 → 5.2.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +30 -0
  4. data/lib/morpheus/api/billing_interface.rb +34 -0
  5. data/lib/morpheus/api/catalog_item_types_interface.rb +9 -0
  6. data/lib/morpheus/api/deploy_interface.rb +1 -1
  7. data/lib/morpheus/api/deployments_interface.rb +20 -1
  8. data/lib/morpheus/api/forgot_password_interface.rb +17 -0
  9. data/lib/morpheus/api/instances_interface.rb +16 -2
  10. data/lib/morpheus/api/rest_interface.rb +0 -6
  11. data/lib/morpheus/api/roles_interface.rb +14 -0
  12. data/lib/morpheus/api/search_interface.rb +13 -0
  13. data/lib/morpheus/api/servers_interface.rb +14 -0
  14. data/lib/morpheus/api/service_catalog_interface.rb +89 -0
  15. data/lib/morpheus/api/usage_interface.rb +18 -0
  16. data/lib/morpheus/cli.rb +7 -3
  17. data/lib/morpheus/cli/apps.rb +6 -27
  18. data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
  19. data/lib/morpheus/cli/backups_command.rb +3 -0
  20. data/lib/morpheus/cli/catalog_item_types_command.rb +622 -0
  21. data/lib/morpheus/cli/cli_command.rb +70 -21
  22. data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -12
  23. data/lib/morpheus/cli/commands/standard/history_command.rb +3 -1
  24. data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
  25. data/lib/morpheus/cli/commands/standard/source_command.rb +1 -1
  26. data/lib/morpheus/cli/commands/standard/update_command.rb +76 -0
  27. data/lib/morpheus/cli/containers_command.rb +14 -24
  28. data/lib/morpheus/cli/cypher_command.rb +6 -2
  29. data/lib/morpheus/cli/deploy.rb +199 -90
  30. data/lib/morpheus/cli/deployments.rb +341 -28
  31. data/lib/morpheus/cli/deploys.rb +206 -41
  32. data/lib/morpheus/cli/error_handler.rb +7 -0
  33. data/lib/morpheus/cli/forgot_password.rb +133 -0
  34. data/lib/morpheus/cli/groups.rb +1 -1
  35. data/lib/morpheus/cli/health_command.rb +59 -2
  36. data/lib/morpheus/cli/hosts.rb +265 -34
  37. data/lib/morpheus/cli/instances.rb +186 -100
  38. data/lib/morpheus/cli/invoices_command.rb +33 -16
  39. data/lib/morpheus/cli/jobs_command.rb +28 -6
  40. data/lib/morpheus/cli/library_option_lists_command.rb +15 -7
  41. data/lib/morpheus/cli/library_option_types_command.rb +5 -2
  42. data/lib/morpheus/cli/logs_command.rb +9 -6
  43. data/lib/morpheus/cli/mixins/accounts_helper.rb +12 -7
  44. data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
  45. data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -3
  46. data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
  47. data/lib/morpheus/cli/mixins/print_helper.rb +46 -21
  48. data/lib/morpheus/cli/mixins/provisioning_helper.rb +100 -4
  49. data/lib/morpheus/cli/network_pools_command.rb +14 -6
  50. data/lib/morpheus/cli/option_types.rb +271 -22
  51. data/lib/morpheus/cli/ping.rb +0 -1
  52. data/lib/morpheus/cli/remote.rb +35 -12
  53. data/lib/morpheus/cli/reports_command.rb +99 -30
  54. data/lib/morpheus/cli/roles.rb +453 -113
  55. data/lib/morpheus/cli/search_command.rb +182 -0
  56. data/lib/morpheus/cli/service_catalog_command.rb +1474 -0
  57. data/lib/morpheus/cli/service_plans_command.rb +2 -2
  58. data/lib/morpheus/cli/setup.rb +1 -1
  59. data/lib/morpheus/cli/shell.rb +33 -11
  60. data/lib/morpheus/cli/storage_providers_command.rb +40 -56
  61. data/lib/morpheus/cli/tasks.rb +29 -32
  62. data/lib/morpheus/cli/usage_command.rb +203 -0
  63. data/lib/morpheus/cli/user_settings_command.rb +1 -0
  64. data/lib/morpheus/cli/users.rb +12 -1
  65. data/lib/morpheus/cli/version.rb +1 -1
  66. data/lib/morpheus/cli/virtual_images.rb +429 -254
  67. data/lib/morpheus/cli/whoami.rb +6 -6
  68. data/lib/morpheus/cli/workflows.rb +34 -41
  69. data/lib/morpheus/formatters.rb +75 -7
  70. data/lib/morpheus/terminal.rb +6 -2
  71. metadata +14 -2
@@ -409,9 +409,9 @@ class Morpheus::Cli::ServicePlanCommand
409
409
  while Morpheus::Cli::OptionTypes.confirm("Add #{price_sets.empty? ? '' : 'another '}price set?", {:default => false}) do
410
410
  price_unit = prompt_price_unit(options)
411
411
 
412
- avail_price_sets ||= @price_sets_interface.list['priceSets'].collect {|it| {'name' => it['name'], 'value' => it['id'], 'priceUnit' => it['priceUnit']}}
412
+ avail_price_sets ||= @price_sets_interface.list({'priceUnit' => price_unit, 'max' => 10000})['priceSets'].collect {|it| {'name' => it['name'], 'value' => it['id'], 'priceUnit' => it['priceUnit']}}
413
413
 
414
- if price_set_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priceSet', 'type' => 'select', 'fieldLabel' => 'Price Set', 'selectOptions' => avail_price_sets.reject {|it| it['priceUnit'] != price_unit}, 'required' => false, 'description' => 'Select Price.'}],options[:options],@api_client,{}, options[:no_prompt], true)['priceSet']
414
+ if price_set_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'priceSet', 'type' => 'select', 'fieldLabel' => 'Price Set', 'selectOptions' => avail_price_sets, 'required' => false, 'description' => 'Select Price.'}],options[:options],@api_client,{}, options[:no_prompt], true)['priceSet']
415
415
  price_set = avail_price_sets.find {|it| it['value'] == price_set_id}
416
416
  price_sets << {'id' => price_set['value'], 'priceUnit' => price_set['priceUnit']}
417
417
  avail_price_sets.reject! {|it| it['value'] == price_set_id}
@@ -9,7 +9,7 @@ class Morpheus::Cli::Setup
9
9
 
10
10
  set_command_name :setup
11
11
 
12
- register_subcommands :init
12
+ # register_subcommands :init
13
13
 
14
14
  # no authorization needed
15
15
  def connect(options={})
@@ -92,6 +92,13 @@ class Morpheus::Cli::Shell
92
92
  def recalculate_auto_complete_commands
93
93
  @morpheus_commands = Morpheus::Cli::CliRegistry.all.keys.reject {|k| [:shell].include?(k) }
94
94
  @shell_commands = [:clear, :history, :reload, :help, :exit]
95
+ @shell_command_descriptions = {
96
+ :clear => "Clear terminal output and move cursor to the top",
97
+ :history => "View morpheus shell command history",
98
+ :reload => "Reload the shell, can be useful when developing",
99
+ :help => "Print this help",
100
+ :exit => "Exit the morpheus shell"
101
+ }
95
102
  @alias_commands = Morpheus::Cli::CliRegistry.all_aliases.keys
96
103
  @exploded_commands = []
97
104
  Morpheus::Cli::CliRegistry.all.each do |cmd, klass|
@@ -336,6 +343,11 @@ class Morpheus::Cli::Shell
336
343
  #Morpheus::Logging::DarkPrinter.puts "Shell command: #{input}"
337
344
  input = input.to_s.strip
338
345
 
346
+ # allow pasting in commands that have 'morpheus ' prefix
347
+ if input[0..(prog_name.size)] == "#{prog_name} "
348
+ input = input[(prog_name.size + 1)..-1] || ""
349
+ end
350
+
339
351
  if !input.empty?
340
352
 
341
353
  if input == 'exit'
@@ -345,26 +357,36 @@ class Morpheus::Cli::Shell
345
357
  return 0
346
358
  #exit 0
347
359
  elsif input == 'help'
360
+ out = ""
348
361
  if @temporary_shell_mode
349
- puts "You are in a (temporary) morpheus shell"
362
+ out << "You are in a (temporary) morpheus shell\n"
350
363
  else
351
- puts "You are in a morpheus shell."
364
+ out << "You are in a morpheus shell.\n"
352
365
  end
353
- puts "See the available commands below."
366
+ out << "See the available commands below.\n"
354
367
 
355
- puts "\nCommands:"
368
+ out << "\nCommands:"
356
369
  # commands = @morpheus_commands + @shell_commands
357
- @morpheus_commands.sort.each {|cmd|
358
- puts "\t#{cmd.to_s}"
370
+ # @morpheus_commands.sort.each {|cmd|
371
+ # out << "\t#{cmd.to_s}\n"
372
+ # }
373
+ sorted_commands = Morpheus::Cli::CliRegistry.all.values.sort { |x,y| x.command_name.to_s <=> y.command_name.to_s }
374
+ sorted_commands.each {|cmd|
375
+ # JD: not ready to show description yet, gotta finish filling in every command first
376
+ # maybe change 'View and manage' to something more concise like 'Manage'
377
+ # out << "\t#{cmd.command_name.to_s.ljust(28, ' ')} #{cmd.command_description}\n"
378
+ out << "\t#{cmd.command_name.to_s}\n"
359
379
  }
360
380
  #puts "\n"
361
- puts "\nShell Commands:"
381
+ out << "\nShell Commands:\n"
362
382
  @shell_commands.each {|cmd|
363
- puts "\t#{cmd.to_s}"
383
+ # out << "\t#{cmd.to_s.ljust(28, ' ')} #{@shell_command_descriptions ? @shell_command_descriptions[cmd] : ''}\n"
384
+ out << "\t#{cmd.to_s}\n"
364
385
  }
365
- puts "\n"
366
- puts "For more information, see https://github.com/gomorpheus/morpheus-cli/wiki"
367
- #print "\n"
386
+ out << "\n"
387
+ out << "For more information, see https://github.com/gomorpheus/morpheus-cli/wiki"
388
+ out << "\n"
389
+ print out
368
390
  return 0
369
391
  elsif input =~ /^\s*#/
370
392
  Morpheus::Logging::DarkPrinter.puts "ignored comment: #{input}" if Morpheus::Logging.debug?
@@ -42,71 +42,39 @@ class Morpheus::Cli::StorageProvidersCommand
42
42
  def list(args)
43
43
  options = {}
44
44
  params = {}
45
+ ref_ids = []
45
46
  optparse = Morpheus::Cli::OptionParser.new do |opts|
46
- opts.banner = subcommand_usage()
47
- build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
47
+ opts.banner = subcommand_usage("[search]")
48
+ build_standard_list_options(opts, options)
48
49
  opts.footer = "List storage buckets."
49
50
  end
50
51
  optparse.parse!(args)
51
- if args.count != 0
52
- print_error Morpheus::Terminal.angry_prompt
53
- puts_error "wrong number of arguments, expected 0 and got #{args.count}\n#{optparse}"
54
- return 1
55
- end
56
52
  connect(options)
57
- begin
58
- params.merge!(parse_list_options(options))
59
- @storage_providers_interface.setopts(options)
60
- if options[:dry_run]
61
- print_dry_run @storage_providers_interface.dry.list(params)
62
- return
63
- end
64
- json_response = @storage_providers_interface.list(params)
65
- storage_providers = json_response["storageBuckets"]
66
- if options[:json]
67
- puts as_json(json_response, options, "storageBuckets")
68
- return 0
69
- elsif options[:yaml]
70
- puts as_yaml(json_response, options, "storageBuckets")
71
- return 0
72
- elsif options[:csv]
73
- puts records_as_csv(storage_providers, options)
74
- return 0
75
- end
76
- title = "Morpheus Storage Buckets"
77
- subtitles = []
78
- subtitles += parse_list_subtitles(options)
79
- print_h1 title, subtitles
80
- if storage_providers.empty?
53
+ if args.count > 0
54
+ options[:phrase] = args.join(" ")
55
+ end
56
+ params.merge!(parse_list_options(options))
57
+ @storage_providers_interface.setopts(options)
58
+ if options[:dry_run]
59
+ print_dry_run @storage_providers_interface.dry.list(params)
60
+ return
61
+ end
62
+ json_response = @storage_providers_interface.list(params)
63
+ storage_buckets = json_response['storageBuckets']
64
+ render_response(json_response, options, 'storageBuckets') do
65
+ print_h1 "Morpheus Storage Buckets", parse_list_subtitles(options), options
66
+ if storage_buckets.empty?
81
67
  print cyan,"No storage buckets found.",reset,"\n"
82
68
  else
83
- rows = storage_providers.collect {|storage_provider|
84
- row = {
85
- id: storage_provider['id'],
86
- name: storage_provider['name'],
87
- provider: format_storage_provider_type(storage_provider),
88
- bucket: format_bucket_name(storage_provider),
89
- backups: storage_provider['defaultBackupTarget'] ? 'Yes' : 'No',
90
- deployments: storage_provider['defaultDeploymentTarget'] ? 'Yes' : 'No',
91
- virtualImages: storage_provider['defaultVirtualImageTarget'] ? 'Yes' : 'No',
92
- }
93
- row
94
- }
95
- columns = [:id, :name, {:provider => {:display_name => "Provider Type".upcase} }, {:bucket => {:display_name => "Bucket Name".upcase} }, :backups, :deployments]
96
- if options[:include_fields]
97
- columns = options[:include_fields]
98
- rows = storage_providers
99
- end
100
- print cyan
101
- print as_pretty_table(rows, columns, options)
102
- print reset
103
- print_results_pagination(json_response, {:label => "storage bucket", :n_label => "storage buckets"})
69
+ print as_pretty_table(storage_buckets, storage_bucket_column_definitions.upcase_keys!, options)
70
+ print_results_pagination(json_response)
104
71
  end
105
72
  print reset,"\n"
106
- return 0
107
- rescue RestClient::Exception => e
108
- print_rest_exception(e, options)
109
- exit 1
73
+ end
74
+ if storage_buckets.empty?
75
+ return 1, "no storage buckets found"
76
+ else
77
+ return 0, nil
110
78
  end
111
79
  end
112
80
 
@@ -1232,6 +1200,22 @@ class Morpheus::Cli::StorageProvidersCommand
1232
1200
 
1233
1201
  private
1234
1202
 
1203
+ def storage_bucket_column_definitions()
1204
+ {
1205
+ "ID" => 'id',
1206
+ "Name" => 'name',
1207
+ # "Description" => 'description',
1208
+ "Provider Type" => lambda {|it| format_storage_provider_type(it) },
1209
+ "Bucket Name" => lambda {|it| format_bucket_name(it) },
1210
+ # "Source" => lambda {|it| it['source'] },
1211
+ "Backups" => lambda {|it| format_boolean(it['defaultBackupTarget']) },
1212
+ "Deployments" => lambda {|it| format_boolean(it['defaultDeploymentTarget']) },
1213
+ "Virtual Images" => lambda {|it| format_boolean(it['defaultVirtualImageTarget']) },
1214
+ # "Archive Snapshots" => lambda {|it| format_boolean(it['copyToStore']) },
1215
+ # "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
1216
+ # "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
1217
+ }
1218
+ end
1235
1219
 
1236
1220
  def get_storage_provider_types()
1237
1221
  [
@@ -27,34 +27,31 @@ class Morpheus::Cli::Tasks
27
27
  params = {}
28
28
  options = {}
29
29
  optparse = Morpheus::Cli::OptionParser.new do |opts|
30
- opts.banner = subcommand_usage()
30
+ opts.banner = subcommand_usage("[search]")
31
31
  opts.on('-t', '--type x,y,z', Array, "Filter by task type code(s)") do |val|
32
32
  params['taskTypeCodes'] = val
33
33
  end
34
- build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote])
34
+ build_standard_list_options(opts, options)
35
+ opts.footer = "List tasks."
35
36
  end
36
37
  optparse.parse!(args)
38
+ connect(options)
37
39
  if args.count > 0
38
- raise_command_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
40
+ options[:phrase] = args.join(" ")
39
41
  end
40
- connect(options)
41
- begin
42
- params.merge!(parse_list_options(options))
43
- @tasks_interface.setopts(options)
44
- if options[:dry_run]
45
- print_dry_run @tasks_interface.dry.list(params)
46
- return
47
- end
48
- json_response = @tasks_interface.list(params)
49
-
50
- render_result = render_with_format(json_response, options, 'tasks')
51
- return 0 if render_result
52
-
42
+ params.merge!(parse_list_options(options))
43
+ @tasks_interface.setopts(options)
44
+ if options[:dry_run]
45
+ print_dry_run @tasks_interface.dry.list(params)
46
+ return
47
+ end
48
+ json_response = @tasks_interface.list(params)
49
+ tasks = json_response['tasks']
50
+ render_response(json_response, options, 'tasks') do
53
51
  title = "Morpheus Tasks"
54
52
  subtitles = []
55
53
  subtitles += parse_list_subtitles(options)
56
54
  print_h1 title, subtitles
57
- tasks = json_response['tasks']
58
55
  if tasks.empty?
59
56
  print cyan,"No tasks found.",reset,"\n"
60
57
  else
@@ -63,11 +60,13 @@ class Morpheus::Cli::Tasks
63
60
  print_results_pagination(json_response)
64
61
  end
65
62
  print reset,"\n"
66
- return 0
67
- rescue RestClient::Exception => e
68
- print_rest_exception(e, options)
69
- exit 1
70
63
  end
64
+ if tasks.empty?
65
+ return 1, "no tasks found"
66
+ else
67
+ return 0, nil
68
+ end
69
+
71
70
  end
72
71
 
73
72
  def get(args)
@@ -334,10 +333,9 @@ class Morpheus::Cli::Tasks
334
333
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
335
334
  end
336
335
  optparse.parse!(args)
337
- if args.count > 1
338
- raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
339
- end
336
+ #verify_args!(args:args, count:1, optparse:optparse)
340
337
  if args[0]
338
+ # task_name = args[0]
341
339
  task_name = args[0]
342
340
  end
343
341
  # if task_name.nil? || task_type_name.nil?
@@ -425,6 +423,9 @@ class Morpheus::Cli::Tasks
425
423
  has_file_content = true
426
424
  it['fieldContext'] = nil
427
425
  it['fieldName'] = 'file'
426
+ # this should be required right!? fix api optionType data plz
427
+ it['required'] = true
428
+ it['defaultValue'] = 'local'
428
429
  else
429
430
  if it['fieldContext'].nil? || it['fieldContext'] == ''
430
431
  it['fieldContext'] = 'taskOptions'
@@ -658,9 +659,7 @@ class Morpheus::Cli::Tasks
658
659
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
659
660
  end
660
661
  optparse.parse!(args)
661
- if args.count != 1
662
- raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
663
- end
662
+ verify_args!(args:args, count:1, optparse:optparse)
664
663
  task_name = args[0]
665
664
  connect(options)
666
665
  begin
@@ -734,7 +733,6 @@ class Morpheus::Cli::Tasks
734
733
 
735
734
  def remove(args)
736
735
  params = {}
737
- task_name = args[0]
738
736
  options = {}
739
737
  optparse = Morpheus::Cli::OptionParser.new do |opts|
740
738
  opts.banner = subcommand_usage("[task]")
@@ -744,10 +742,8 @@ class Morpheus::Cli::Tasks
744
742
  end
745
743
  end
746
744
  optparse.parse!(args)
747
- if args.count < 1
748
- puts optparse
749
- exit 1
750
- end
745
+ verify_args!(args:args, count:1, optparse:optparse)
746
+ task_name = args[0]
751
747
  connect(options)
752
748
  begin
753
749
  task = find_task_by_name_or_id(task_name)
@@ -820,6 +816,7 @@ class Morpheus::Cli::Tasks
820
816
  if args.count != 1
821
817
  raise_command_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
822
818
  end
819
+ verify_args!(args:args, count:1, optparse:optparse)
823
820
  task_name = args[0]
824
821
  connect(options)
825
822
  begin
@@ -0,0 +1,203 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ # CLI command usages
4
+ # UI is Costing - Usage
5
+ # API is /usage and returns usages
6
+ class Morpheus::Cli::UsageCommand
7
+ include Morpheus::Cli::CliCommand
8
+ include Morpheus::Cli::OptionSourceHelper
9
+
10
+ set_command_name :'usage'
11
+
12
+ register_subcommands :list, :get
13
+
14
+ def connect(opts)
15
+ @api_client = establish_remote_appliance_connection(opts)
16
+ @usage_interface = @api_client.usage
17
+ end
18
+
19
+ def handle(args)
20
+ handle_subcommand(args)
21
+ end
22
+
23
+ def list(args)
24
+ options = {}
25
+ params = {}
26
+ ref_ids = []
27
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
28
+ opts.banner = subcommand_usage("[search]")
29
+ opts.on( '-t', '--type TYPE', "Filter by type" ) do |val|
30
+ params['type'] = parse_usage_type(val)
31
+ end
32
+ opts.on( '-c', '--cloud CLOUD', "Filter by cloud" ) do |val|
33
+ options[:cloud] = val
34
+ end
35
+ opts.on('--start DATE', String, "Start date in the format YYYY-MM-DD.") do |val|
36
+ params['startDate'] = val # parse_time(val).utc.iso8601
37
+ end
38
+ opts.on('--end DATE', String, "End date in the format YYYY-MM-DD. Default is the current date.") do |val|
39
+ params['endDate'] = val # parse_time(val).utc.iso8601
40
+ end
41
+ opts.on('--sigdig DIGITS', "Significant digits when rounding cost values for display as currency. Default is 5.") do |val|
42
+ options[:sigdig] = val.to_i
43
+ end
44
+ build_standard_list_options(opts, options)
45
+ opts.footer = "List usages."
46
+ end
47
+ optparse.parse!(args)
48
+ connect(options)
49
+ # verify_args!(args:args, optparse:optparse, count:0)
50
+ if args.count > 0
51
+ options[:phrase] = args.join(" ")
52
+ end
53
+ params.merge!(parse_list_options(options))
54
+ # --cloud
55
+ if options[:cloud]
56
+ params['cloud'] = parse_id_list(options[:cloud]).collect {|cloud_id|
57
+ if cloud_id.to_s =~ /\A\d{1,}\Z/
58
+ cloud_id
59
+ else
60
+ cloud = find_cloud_option(cloud_id)
61
+ return 1 if cloud.nil?
62
+ cloud['id']
63
+ end
64
+ }
65
+ end
66
+
67
+ @usage_interface.setopts(options)
68
+ if options[:dry_run]
69
+ print_dry_run @usage_interface.dry.list(params)
70
+ return
71
+ end
72
+ json_response = @usage_interface.list(params)
73
+ usages = json_response[usage_list_key]
74
+ render_response(json_response, options, usage_list_key) do
75
+ print_h1 "Morpheus Usages", parse_list_subtitles(options), options
76
+ if usages.empty?
77
+ print cyan,"No usages found.",reset,"\n"
78
+ else
79
+ list_columns = {
80
+ "ID" => 'id',
81
+ "Cloud" => 'zoneName',
82
+ "Type" => lambda {|it| format_usage_type(it) },
83
+ "Name" => 'name',
84
+ "Plan" => 'planName',
85
+ "Start Date" => lambda {|it| format_local_dt(it['startDate']) },
86
+ "End Date" => lambda {|it| format_local_dt(it['endDate']) },
87
+ "Usage Status" => lambda {|it| format_usage_status(it) },
88
+ "Usage Cost" => lambda {|it| format_money(it['costDetails']['cost'], it['currency'] || 'USD', {sigdig: (options[:sigdig] || 5)}) },
89
+ "Usage Price" => lambda {|it| format_money(it['price'], it['currency'] || 'USD', {sigdig: (options[:sigdig] || 5)}) },
90
+ }
91
+ print as_pretty_table(usages, list_columns.upcase_keys!, options)
92
+ print_results_pagination(json_response)
93
+ end
94
+ print reset,"\n"
95
+ end
96
+ if usages.empty?
97
+ return 1, "no usages found"
98
+ else
99
+ return 0, nil
100
+ end
101
+ end
102
+
103
+ def get(args)
104
+ params = {}
105
+ options = {}
106
+ optparse = Morpheus::Cli::OptionParser.new do |opts|
107
+ opts.banner = subcommand_usage("[usage]")
108
+ build_standard_get_options(opts, options)
109
+ opts.footer = <<-EOT
110
+ Get details about a specific usage.
111
+ [usage] is required. This is the id of a usage record.
112
+ EOT
113
+ end
114
+ optparse.parse!(args)
115
+ verify_args!(args:args, optparse:optparse, min:1)
116
+ connect(options)
117
+ id_list = parse_id_list(args)
118
+ return run_command_for_each_arg(id_list) do |arg|
119
+ _get(arg, params, options)
120
+ end
121
+ end
122
+
123
+ def _get(id, params, options)
124
+ usage = nil
125
+ @usage_interface.setopts(options)
126
+ if options[:dry_run]
127
+ print_dry_run @usage_interface.dry.get(id, params)
128
+ return
129
+ end
130
+ json_response = @usage_interface.get(id, params)
131
+ usage = json_response[usage_object_key]
132
+ render_response(json_response, options, usage_object_key) do
133
+ print_h1 "Usage Details", [], options
134
+ print cyan
135
+ show_columns = {
136
+ "ID" => 'id',
137
+ "Cloud" => 'zoneName',
138
+ "Type" => lambda {|it| format_usage_type(it) },
139
+ "Name" => 'name',
140
+ "Plan" => 'planName',
141
+ "Start Date" => lambda {|it| format_local_dt(it['startDate']) },
142
+ "End Date" => lambda {|it| format_local_dt(it['endDate']) },
143
+ "Usage Status" => lambda {|it| format_usage_status(it) },
144
+ "Usage Cost" => lambda {|it| format_money(it['costDetails']['cost'], it['currency'] || 'USD', {sigdig: (options[:sigdig] || 5)}) },
145
+ "Usage Price" => lambda {|it| format_money(it['price'], it['currency'] || 'USD', {sigdig: (options[:sigdig] || 5)}) },
146
+ }
147
+ print_description_list(show_columns, usage)
148
+
149
+ # print_h2 "Applicable Prices"
150
+
151
+ print reset,"\n"
152
+ end
153
+ return 0, nil
154
+ end
155
+
156
+ private
157
+
158
+ def usage_object_key
159
+ 'usage'
160
+ end
161
+
162
+ def usage_list_key
163
+ 'usages'
164
+ end
165
+
166
+ def format_usage_type(usage)
167
+ #return usage['costDetails']['refType']
168
+ ref_type = usage['costDetails'] ? usage['costDetails']['refType'].to_s : ''
169
+ if ref_type == 'discoveredServer'
170
+ 'Discovered'
171
+ elsif ref_type == 'computeServer'
172
+ 'Host'
173
+ elsif ref_type == 'container'
174
+ 'Container'
175
+ else
176
+ ref_type.to_s
177
+ end
178
+ end
179
+
180
+ def parse_usage_type(val)
181
+ type_string = val.to_s.downcase
182
+ if type_string == 'discoveredServer'
183
+ 'discoveredServer'
184
+ elsif type_string == 'host'
185
+ 'computeServer'
186
+ elsif type_string == 'container'
187
+ 'container'
188
+ else
189
+ val
190
+ end
191
+ end
192
+
193
+ def format_usage_status(usage, return_color=cyan)
194
+ #return usage['status'].to_s.capitalize
195
+ status_string = usage['status'].to_s
196
+ if status_string == 'stopped'
197
+ return "#{red}#{status_string.upcase}#{return_color}"
198
+ else
199
+ return "#{green}#{status_string.upcase}#{return_color}"
200
+ end
201
+ end
202
+
203
+ end