morpheus-cli 8.0.1 → 8.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8074c5d41cd8ca2aa6f199a0b85f22f7c2b8d3647b2788604d42424b7abbd9b
4
- data.tar.gz: 8176b21a71b63466b537ca4d43933e06411ae374cbb159ab451f4e37042299e5
3
+ metadata.gz: b071ad7a069db88e11023de144dad8ad640f49b6a18becdfa60cd1e04312397f
4
+ data.tar.gz: b1deba83d4decb51b824fabfca0d8a615dbd17e6df7e07296de3a8dc3606f945
5
5
  SHA512:
6
- metadata.gz: 05414d569b3e9d323ca0ebf0ff86778e9656f84b92af1a2e6520e826351dc444eb1c6d6721ef7137ffbe603be703832dcd15f4e14c31f28005b6de7c2cc454f8
7
- data.tar.gz: fca09ddb93cf6cc58401d1652803a61d220fe9999427a931b0fed515c5a8e0a2933013299323722739a7f65c9b9b42edffe4a62972cad85e9b5651a4fcded2df
6
+ metadata.gz: '04509b5731b2f5713189498b3a166b62735911c7c178d6480c5d54d4fd68827ef16f21431d5b7c49ce2209dca14dc402c65dc59e90268979b310855a08705598'
7
+ data.tar.gz: 179f4442f70f2f634746a11211f435ae119abd9dc0839e06c16142018afa3809bcdc995cc96ca3967734d06e578b80f7a6a680dbe3ba7c4bf643cc6318cb03d2
data/Dockerfile CHANGED
@@ -1,5 +1,5 @@
1
1
  FROM ruby:2.7.5
2
2
 
3
- RUN gem install morpheus-cli -v 8.0.1
3
+ RUN gem install morpheus-cli -v 8.0.3
4
4
 
5
5
  ENTRYPOINT ["morpheus"]
@@ -1278,7 +1278,7 @@ module Morpheus
1278
1278
  elsif options[:remote_url]
1279
1279
  credentials = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url)
1280
1280
  unless options[:skip_login]
1281
- @wallet = credentials.request_credentials(options, @do_save_credentials)
1281
+ @wallet = credentials.request_credentials(options.merge({dry_run:false}), @do_save_credentials)
1282
1282
  end
1283
1283
  else
1284
1284
  credentials = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url)
@@ -1293,7 +1293,7 @@ module Morpheus
1293
1293
 
1294
1294
  if @wallet.nil? || @wallet['access_token'].nil?
1295
1295
  unless options[:skip_login]
1296
- @wallet = credentials.request_credentials(options, @do_save_credentials)
1296
+ @wallet = credentials.request_credentials(options.merge({dry_run:false}), @do_save_credentials)
1297
1297
  end
1298
1298
  end
1299
1299
 
@@ -1767,7 +1767,22 @@ module Morpheus
1767
1767
  output = records.collect { |record|
1768
1768
  options[:select_fields].collect { |field|
1769
1769
  value = get_object_value(record, field)
1770
- value.is_a?(String) ? value : JSON.fast_generate(value)
1770
+ if value.is_a?(String)
1771
+ value
1772
+ else
1773
+ if options[:json]
1774
+ as_json(value, options)
1775
+ elsif options[:yaml]
1776
+ output = as_yaml(value, options)
1777
+ elsif options[:csv]
1778
+ as_csv(value, nil, options)
1779
+ else
1780
+ # default behavior
1781
+ # value.is_a?(String) ? value : as_json(value, options)
1782
+ do_pretty = options.key?(:pretty_json) ? options[:pretty_json] : false # or true?
1783
+ do_pretty ? JSON.pretty_generate(value) : JSON.fast_generate(value)
1784
+ end
1785
+ end
1771
1786
  }.join(options[:delim] || ",")
1772
1787
  }.join(options[:newline] || "\n")
1773
1788
  elsif options[:json]
@@ -6,6 +6,7 @@ class Morpheus::Cli::Clusters
6
6
  include Morpheus::Cli::ProcessesHelper
7
7
  include Morpheus::Cli::WhoamiHelper
8
8
  include Morpheus::Cli::AccountsHelper
9
+ include Morpheus::Cli::ExecutionRequestHelper
9
10
 
10
11
  register_subcommands :list, :count, :get, :view, :add, :update, :remove, :logs, :history, {:'history-details' => :history_details}, {:'history-event' => :history_event_details}
11
12
  register_subcommands :list_workers, :add_worker, :remove_worker, :update_worker_count
@@ -607,7 +608,7 @@ class Morpheus::Cli::Clusters
607
608
  end
608
609
 
609
610
  # Controller type
610
- server_types = @server_types_interface.list({computeTypeId: cluster_type['controllerTypes'].first['id'], zoneTypeId: cloud['zoneType']['id'], useZoneProvisionTypes: true})['serverTypes'].reject {|it| it['provisionType']['code'] == 'manual'}
611
+ server_types = @server_types_interface.list({computeTypeId: cluster_type['controllerTypes'].first['id'], zoneTypeId: cloud['zoneType']['id'], useZoneProvisionTypes: true})['serverTypes'].reject {|it| it['provisionType']['code'] == 'manual'} unless ['kubernetes-cluster', 'mvm-cluster'].include?(cluster_type_code)
611
612
  controller_provision_type = nil
612
613
  resource_pool = nil
613
614
 
@@ -802,6 +803,9 @@ class Morpheus::Cli::Clusters
802
803
  opts.on('--managed [on|off]', String, "Can be used to enable / disable managed cluster. Default is on") do |val|
803
804
  options[:managed] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
804
805
  end
806
+ opts.on('--useAgent [on|off]', String, "Use the Agent to relay communications for the Kubernetes API instead of direct.") do |val|
807
+ options[:useAgent] = val.to_s
808
+ end
805
809
  opts.on('--autoRecoverPowerState [on|off]', String, "Automatically Power On VMs") do |val|
806
810
  options[:autoRecoverPowerState] = val.to_s == 'on' || val.to_s == 'true' || val.to_s == '1' || val.to_s == ''
807
811
  end
@@ -855,6 +859,7 @@ class Morpheus::Cli::Clusters
855
859
  cluster_payload['refresh'] = options[:refresh] if options[:refresh] == true
856
860
  cluster_payload['tenant'] = options[:tenant] if !options[:tenant].nil?
857
861
  cluster_payload['integrations'] = options[:integrations] if !options[:integrations].nil?
862
+ cluster_payload['useAgent'] = options[:useAgent] if !options[:useAgent].nil?
858
863
  payload = {"cluster" => cluster_payload}
859
864
  end
860
865
 
@@ -3004,6 +3009,12 @@ class Morpheus::Cli::Clusters
3004
3009
  options = {}
3005
3010
  optparse = Morpheus::Cli::OptionParser.new do |opts|
3006
3011
  opts.banner = subcommand_usage( "[cluster] [options]")
3012
+ opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val|
3013
+ options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
3014
+ end
3015
+ opts.on(nil, '--no-refresh', "Do not refresh" ) do
3016
+ options[:no_refresh] = true
3017
+ end
3007
3018
  build_option_type_options(opts, options, add_datastore_option_types)
3008
3019
  build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
3009
3020
  opts.footer = "Add datastore to a cluster.\n" +
@@ -3059,11 +3070,19 @@ class Morpheus::Cli::Clusters
3059
3070
  json_response = @clusters_interface.create_datastore(cluster['id'], payload)
3060
3071
  if options[:json]
3061
3072
  puts as_json(json_response)
3062
- elsif json_response['success']
3063
- if json_response['msg'] == nil
3064
- print_green_success "Added datastore to cluster #{cluster['name']}"
3073
+ else
3074
+ if json_response['success']
3075
+ if json_response['msg'] == nil
3076
+ print_green_success "Adding datastore to cluster #{cluster['name']}"
3077
+ else
3078
+ print_green_success json_response['msg']
3079
+ end
3080
+ execution_id = json_response['executionId']
3081
+ if !options[:no_refresh] && execution_id
3082
+ wait_for_execution_request(json_response['executionId'], options.merge({waiting_status:['new', 'pending', 'executing']}))
3083
+ end
3065
3084
  else
3066
- print_green_success json_response['msg']
3085
+ print_red_alert "Failed to create cluster datastore #{json_response['msg']}"
3067
3086
  end
3068
3087
  end
3069
3088
  return 0
@@ -3074,6 +3093,7 @@ class Morpheus::Cli::Clusters
3074
3093
  end
3075
3094
 
3076
3095
  def remove_datastore(args)
3096
+ default_refresh_interval = 5
3077
3097
  params = {}
3078
3098
  options = {}
3079
3099
  optparse = Morpheus::Cli::OptionParser.new do |opts|
@@ -3081,6 +3101,12 @@ class Morpheus::Cli::Clusters
3081
3101
  opts.on( '-f', '--force', "Force Delete" ) do
3082
3102
  params[:force] = 'on'
3083
3103
  end
3104
+ opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val|
3105
+ options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
3106
+ end
3107
+ opts.on(nil, '--no-refresh', "Do not refresh" ) do
3108
+ options[:no_refresh] = true
3109
+ end
3084
3110
  build_standard_remove_options(opts, options)
3085
3111
  opts.footer = "Delete a datastore from a cluster.\n" +
3086
3112
  "[cluster] is required. This is the name or id of an existing cluster.\n" +
@@ -3114,12 +3140,18 @@ class Morpheus::Cli::Clusters
3114
3140
  return
3115
3141
  end
3116
3142
  json_response = @clusters_interface.destroy_datastore(cluster['id'], datastore['id'], params)
3117
- render_response(json_response, options) do
3118
- msg = "Datastore #{datastore['name']} is being removed from cluster #{cluster['name']}..."
3119
- if json_response['msg']
3120
- msg = json_response['msg']
3143
+ if options[:json]
3144
+ puts as_json(json_response)
3145
+ else
3146
+ if json_response['success']
3147
+ print_green_success "Datastore #{datastore['name']} is being removed from cluster #{cluster['name']}"
3148
+ execution_id = json_response['executionId']
3149
+ if !options[:no_refresh] && execution_id
3150
+ wait_for_execution_request(execution_id, options.merge({waiting_status:['new', 'pending', 'executing']}))
3151
+ end
3152
+ else
3153
+ print_red_alert "Failed to remove cluster datastore #{json_response['msg']}"
3121
3154
  end
3122
- print_green_success msg
3123
3155
  end
3124
3156
  return 0, nil
3125
3157
  end
@@ -3752,7 +3784,7 @@ class Morpheus::Cli::Clusters
3752
3784
  subtitles << " Process ID: #{process_id}"
3753
3785
  subtitles += parse_list_subtitles(options)
3754
3786
  print_h1 title, subtitles, options
3755
- print_process_details(process)
3787
+ print_process_details(process, options)
3756
3788
 
3757
3789
  print_h2 "Process Events", options
3758
3790
  process_events = process['events'] || process['processEvents'] || []
@@ -3971,7 +4003,7 @@ class Morpheus::Cli::Clusters
3971
4003
  subtitles = []
3972
4004
  subtitles += parse_list_subtitles(options)
3973
4005
  print_h1 title, subtitles, options
3974
- print_process_event_details(process_event)
4006
+ print_process_event_details(process_event, options)
3975
4007
  print reset, "\n"
3976
4008
  return 0
3977
4009
  end
@@ -3983,37 +4015,6 @@ class Morpheus::Cli::Clusters
3983
4015
 
3984
4016
  private
3985
4017
 
3986
- def print_process_event_details(process_event, options={})
3987
- # process_event =~ process
3988
- description_cols = {
3989
- "Process ID" => lambda {|it| it['processId'] },
3990
- "Event ID" => lambda {|it| it['id'] },
3991
- "Name" => lambda {|it| it['displayName'] },
3992
- "Description" => lambda {|it| it['description'] },
3993
- "Process Type" => lambda {|it| it['processType'] ? (it['processType']['name'] || it['processType']['code']) : it['processTypeName'] },
3994
- "Created By" => lambda {|it| it['createdBy'] ? (it['createdBy']['displayName'] || it['createdBy']['username']) : '' },
3995
- "Start Date" => lambda {|it| format_local_dt(it['startDate']) },
3996
- "End Date" => lambda {|it| format_local_dt(it['endDate']) },
3997
- "Duration" => lambda {|it| format_process_duration(it) },
3998
- "Status" => lambda {|it| format_process_status(it) },
3999
- }
4000
- print_description_list(description_cols, process_event)
4001
-
4002
- if process_event['error']
4003
- print_h2 "Error", options
4004
- print reset
4005
- #puts format_process_error(process_event)
4006
- puts process_event['error'].to_s.strip
4007
- end
4008
-
4009
- if process_event['output']
4010
- print_h2 "Output", options
4011
- print reset
4012
- #puts format_process_error(process_event)
4013
- puts process_event['output'].to_s.strip
4014
- end
4015
- end
4016
-
4017
4018
  def print_clusters_table(clusters, opts={})
4018
4019
  table_color = opts[:color] || cyan
4019
4020
  rows = clusters.collect do |cluster|
@@ -4535,7 +4536,12 @@ class Morpheus::Cli::Clusters
4535
4536
  elsif resource_pool_options.count > 1 && !options[:no_prompt]
4536
4537
  resource_pool_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'resourcePool', 'type' => 'select', 'fieldLabel' => 'Resource Pool', 'selectOptions' => resource_pool_options, 'required' => true, 'skipSingleOption' => true, 'description' => 'Select resource pool.'}],options[:options],api_client, {})['resourcePool']
4537
4538
  else
4538
- resource_pool_id = resource_pool_options.first['id']
4539
+ first_option = resource_pool_options.find {|it| !it['id'].nil? }
4540
+ if first_option.nil?
4541
+ print_red_alert "Cloud #{cloud['name']} has no available resource pools"
4542
+ exit 1
4543
+ end
4544
+ resource_pool_id = first_option['id']
4539
4545
  end
4540
4546
  if resource_pool_id.to_s["poolGroup-"]
4541
4547
  resource_pool = @resource_pool_groups_interface.get(resource_pool_id)['resourcePoolGroup']
@@ -1337,14 +1337,20 @@ class Morpheus::Cli::Hosts
1337
1337
  payload[:server][:plan] = {id: service_plan["id"]}
1338
1338
 
1339
1339
  # fetch volumes
1340
- volumes_response = @servers_interface.volumes(server['id'])
1341
- current_volumes = volumes_response['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
1340
+ current_volumes = nil
1341
+ if server['volumes']
1342
+ current_volumes = server['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
1343
+ else
1344
+ volumes_response = @servers_interface.volumes(server['id'])
1345
+ current_volumes = volumes_response['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
1346
+ end
1342
1347
 
1343
1348
  # prompt for volumes
1344
1349
  vol_options = options
1345
1350
  vol_options['siteId'] = group_id
1346
1351
  vol_options['zoneId'] = cloud_id
1347
- volumes = prompt_resize_volumes(current_volumes, service_plan, provision_type, vol_options)
1352
+ vol_options['resourcePoolId'] = server['resourcePool']['id'] if server['resourcePool']
1353
+ volumes = prompt_resize_volumes(current_volumes, service_plan, provision_type, vol_options, server)
1348
1354
  if !volumes.empty?
1349
1355
  payload[:volumes] = volumes
1350
1356
  end
@@ -2756,7 +2756,10 @@ class Morpheus::Cli::Instances
2756
2756
  connect(options)
2757
2757
  instance = find_instance_by_name_or_id(args[0])
2758
2758
  return 1, "instance not found" if instance.nil?
2759
-
2759
+ # need to load full instance details in case fetched by name
2760
+ if instance['containerDetails'].nil?
2761
+ instance = find_instance_by_id(instance['id'])
2762
+ end
2760
2763
  payload = {}
2761
2764
  if options[:payload]
2762
2765
  payload = options[:payload]
@@ -2811,13 +2814,24 @@ class Morpheus::Cli::Instances
2811
2814
  payload["instance"]["plan"] = {"id" => service_plan["id"]}
2812
2815
 
2813
2816
  volumes_response = @instances_interface.volumes(instance['id'])
2814
- current_volumes = volumes_response['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
2817
+ current_volumes = nil
2815
2818
 
2816
2819
  # prompt for volumes
2817
2820
  vol_options = options
2818
2821
  vol_options['siteId'] = group_id
2819
2822
  vol_options['zoneId'] = cloud_id
2820
- volumes = prompt_resize_volumes(current_volumes, service_plan, provision_type, vol_options)
2823
+ vol_options['resourcePoolId'] = resource_pool_id # server['resourcePool']['id'] if server['resourcePool']
2824
+ server = instance['containerDetails'][0]['server'] rescue nil
2825
+ if server.nil?
2826
+ Morpheus::Logging::DarkPrinter.puts "Failed to load server info"
2827
+ volumes_response = @instances_interface.volumes(instance['id'])
2828
+ current_volumes = volumes_response['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
2829
+ else
2830
+ # or just use instance['volumes'] ?
2831
+ current_volumes = server['volumes'].sort {|x,y| x['displayOrder'] <=> y['displayOrder'] }
2832
+ end
2833
+ vol_options['resourcePoolId'] = server['resourcePool']['id'] if server && server['resourcePool']
2834
+ volumes = prompt_resize_volumes(current_volumes, service_plan, provision_type, vol_options, server)
2821
2835
  if !volumes.empty?
2822
2836
  payload["volumes"] = volumes
2823
2837
  end
@@ -2907,6 +2921,12 @@ class Morpheus::Cli::Instances
2907
2921
  opts.on( '--description VALUE', String, "Snapshot Description." ) do |val|
2908
2922
  options[:options]['description'] = val
2909
2923
  end
2924
+ opts.on('--refresh [SECONDS]', String, "Refresh until execution is complete. Default interval is #{default_refresh_interval} seconds.") do |val|
2925
+ options[:refresh_interval] = val.to_s.empty? ? default_refresh_interval : val.to_f
2926
+ end
2927
+ opts.on(nil, '--no-refresh', "Do not refresh" ) do
2928
+ options[:no_refresh] = true
2929
+ end
2910
2930
  build_standard_add_options(opts, options, [:auto_confirm])
2911
2931
  opts.footer = <<-EOT
2912
2932
  Create a snapshot for an instance.
@@ -2935,6 +2955,18 @@ EOT
2935
2955
  json_response = @instances_interface.snapshot(instance['id'], payload)
2936
2956
  render_response(json_response, options, 'snapshots') do
2937
2957
  print_green_success "Snapshot initiated."
2958
+ process_id = json_response['processIds'][0] rescue nil
2959
+ if process_id
2960
+ unless options[:no_refresh]
2961
+ process = wait_for_process_execution(process_id, options)
2962
+ snapshot_id = process['resultId']
2963
+ if snapshot_id
2964
+ Morpheus::Cli::Snapshots.new.handle(["get", snapshot_id] + (options[:remote] ? ["-r",options[:remote]] : []))
2965
+ end
2966
+ end
2967
+ else
2968
+ # puts "No process returned"
2969
+ end
2938
2970
  end
2939
2971
  return 0, nil
2940
2972
  end
@@ -3693,7 +3725,7 @@ EOT
3693
3725
  if options[:json]
3694
3726
  puts as_json(json_response, options)
3695
3727
  else
3696
- print_green_success "Snapshots attaced to instance #{instance['name']} queued for deletion."
3728
+ print_green_success "Snapshots attached to instance #{instance['name']} queued for deletion."
3697
3729
  end
3698
3730
  return 0
3699
3731
 
@@ -4482,7 +4514,7 @@ EOT
4482
4514
  subtitles << " Process ID: #{process_id}"
4483
4515
  subtitles += parse_list_subtitles(options)
4484
4516
  print_h1 title, subtitles, options
4485
- print_process_details(process)
4517
+ print_process_details(process, options)
4486
4518
 
4487
4519
  print_h2 "Process Events", options
4488
4520
  process_events = process['events'] || process['processEvents'] || []
@@ -5488,67 +5520,6 @@ private
5488
5520
  {'fieldName' => 'maxDisk', 'fieldLabel' => 'Max Disk', 'type' => 'number', 'description' => 'Maximum storage percent (0-100)'},
5489
5521
  ]
5490
5522
  end
5491
-
5492
- def print_process_details(process)
5493
- description_cols = {
5494
- "Process ID" => lambda {|it| it['id'] },
5495
- "Name" => lambda {|it| it['displayName'] },
5496
- "Description" => lambda {|it| it['description'] },
5497
- "Process Type" => lambda {|it| it['processType'] ? (it['processType']['name'] || it['processType']['code']) : it['processTypeName'] },
5498
- "Created By" => lambda {|it| it['createdBy'] ? (it['createdBy']['displayName'] || it['createdBy']['username']) : '' },
5499
- "Start Date" => lambda {|it| format_local_dt(it['startDate']) },
5500
- "End Date" => lambda {|it| format_local_dt(it['endDate']) },
5501
- "Duration" => lambda {|it| format_process_duration(it) },
5502
- "Status" => lambda {|it| format_process_status(it) },
5503
- # "# Events" => lambda {|it| (it['events'] || []).size() },
5504
- }
5505
- print_description_list(description_cols, process)
5506
-
5507
- if process['error']
5508
- print_h2 "Error", options
5509
- print reset
5510
- #puts format_process_error(process_event)
5511
- puts process['error'].to_s.strip
5512
- end
5513
-
5514
- if process['output']
5515
- print_h2 "Output", options
5516
- print reset
5517
- #puts format_process_error(process_event)
5518
- puts process['output'].to_s.strip
5519
- end
5520
- end
5521
-
5522
- def print_process_event_details(process_event, options={})
5523
- # process_event =~ process
5524
- description_cols = {
5525
- "Process ID" => lambda {|it| it['processId'] },
5526
- "Event ID" => lambda {|it| it['id'] },
5527
- "Name" => lambda {|it| it['displayName'] },
5528
- "Description" => lambda {|it| it['description'] },
5529
- "Process Type" => lambda {|it| it['processType'] ? (it['processType']['name'] || it['processType']['code']) : it['processTypeName'] },
5530
- "Created By" => lambda {|it| it['createdBy'] ? (it['createdBy']['displayName'] || it['createdBy']['username']) : '' },
5531
- "Start Date" => lambda {|it| format_local_dt(it['startDate']) },
5532
- "End Date" => lambda {|it| format_local_dt(it['endDate']) },
5533
- "Duration" => lambda {|it| format_process_duration(it) },
5534
- "Status" => lambda {|it| format_process_status(it) },
5535
- }
5536
- print_description_list(description_cols, process_event)
5537
-
5538
- if process_event['error']
5539
- print_h2 "Error", options
5540
- print reset
5541
- #puts format_process_error(process_event)
5542
- puts process_event['error'].to_s.strip
5543
- end
5544
-
5545
- if process_event['output']
5546
- print_h2 "Output", options
5547
- print reset
5548
- #puts format_process_error(process_event)
5549
- puts process_event['output'].to_s.strip
5550
- end
5551
- end
5552
5523
 
5553
5524
  def update_wiki_page_option_types
5554
5525
  [
@@ -845,7 +845,7 @@ class Morpheus::Cli::LibraryClusterLayoutsCommand
845
845
  end
846
846
 
847
847
  def find_layout_by_name(name)
848
- layouts = @library_cluster_layouts_interface.list(instance_type_id, {name: name.to_s})['layouts']
848
+ layouts = @library_cluster_layouts_interface.list({name: name.to_s})['layouts']
849
849
  if layouts.empty?
850
850
  print_red_alert "Cluster layout not found by name #{name}"
851
851
  return nil
@@ -295,7 +295,7 @@ class Morpheus::Cli::Processes
295
295
  subtitles << " Process ID: #{process_id}"
296
296
  subtitles += parse_list_subtitles(options)
297
297
  print_h1 title, subtitles
298
- print_process_details(process)
298
+ print_process_details(process, options)
299
299
 
300
300
  print_h2 "Process Events"
301
301
  process_events = process['events'] || process['processEvents'] || []
@@ -456,7 +456,7 @@ EOT
456
456
  subtitles = []
457
457
  subtitles += parse_list_subtitles(options)
458
458
  print_h1 title, subtitles
459
- print_process_event_details(process_event)
459
+ print_process_event_details(process_event, options)
460
460
  print reset, "\n"
461
461
  return 0
462
462
  end
@@ -635,8 +635,8 @@ class Morpheus::Cli::Shell
635
635
  # @return Hash like {:commands => [], :command_count => total}
636
636
  def load_history_commands(options={})
637
637
  phrase = options[:phrase]
638
- sort_key = options[:sort] ? options[:sort].to_sym : nil
639
-
638
+ #sort_key = options[:sort] ? options[:sort].to_sym : nil
639
+ #direction = options[:direction] # default sort is reversed to get newest first
640
640
  offset = options[:offset].to_i > 0 ? options[:offset].to_i : 0
641
641
  max = options[:max].to_i > 0 ? options[:max].to_i : 25
642
642
 
@@ -648,40 +648,21 @@ class Morpheus::Cli::Shell
648
648
  # collect records as [{:number => 1, :command => "instances list"}, etc]
649
649
  history_records = []
650
650
  history_count = 0
651
-
652
- # sort is a bit different for this command, the default sort is by number
653
- # it sorts oldest -> newest, but shows the very last page by default.
654
- if options[:sort] && ![:number, :command].include?(options[:sort])
655
- sort_key = :number # nil
656
- end
657
651
 
658
- if options[:phrase] || sort_key || options[:direction] || options[:offset]
659
- # this could be a large object...need to index our shell_history file lol
660
- sort_key ||= :number
661
- history_records = @history.keys.collect { |k| {number: k, command: @history[k]} }
662
- if options[:direction] == 'desc'
663
- history_records = history_records.sort {|x,y| y[sort_key] <=> x[sort_key] }
664
- else
665
- history_records = history_records.sort {|x,y| x[sort_key] <=> y[sort_key] }
666
- end
667
- if phrase
668
- history_records = history_records.select {|it| it[:command].include?(phrase) || it[:number].to_s == phrase }
669
- end
670
- command_count = history_records.size
671
- history_records = history_records[offset..(max-1)]
672
- else
673
- # default should try to be as fast as possible..
674
- # no searching or sorting, default order by :number works
675
- if offset != 0
676
- cmd_numbers = @history.keys.last(max + offset).first(max)
677
- else
678
- cmd_numbers = @history.keys.last(max)
679
- end
680
- history_records = cmd_numbers.collect { |k| {number: k, command: @history[k]} }
681
- command_count = @history.size
652
+ # only go so far back in command history, 1 million commands
653
+ # this could be a large object...need to index our shell_history file lol
654
+ # todo: this max needs to be done in load_history_from_log_file()
655
+ history_keys = @history.keys.last(1000000).reverse
656
+ # filter by phrase
657
+ if phrase
658
+ history_keys = history_keys.select {|k| (@history[k] && @history[k].include?(phrase)) || k.to_s == phrase }
682
659
  end
660
+ # no offset, just max
661
+ history_records = history_keys.first(max).collect { |k| {number: k, command: @history[k]} }
662
+ command_count = history_keys.size
663
+
683
664
  meta = {size:history_records.size, total:command_count.to_i, max:max, offset:offset}
684
- return {:commands => history_records, :command_count => command_count, :meta => meta}
665
+ return {commands: history_records, command_count: command_count, meta: meta}
685
666
  end
686
667
 
687
668
  def print_history(options={})
@@ -696,16 +677,14 @@ class Morpheus::Cli::Shell
696
677
  end
697
678
  else
698
679
  print cyan
680
+ # by default show old->new as the shell history should bash history
681
+ history_records.reverse! unless options[:direction] == "desc"
699
682
  history_records.each do |history_record|
700
683
  puts "#{history_record[:number].to_s.rjust(3, ' ')} #{history_record[:command]}"
701
684
  end
702
685
  if options[:show_pagination]
703
- if options[:phrase] || options[:sort] || options[:direction] || options[:offset]
704
- print_results_pagination(history_result[:meta])
705
- else
706
- # default order is weird, it's the last page of results, 1-25 is misleading and showing the indexes is stranger
707
- print_results_pagination(history_result[:meta], {:message =>"Viewing most recent %{size} of %{total} %{label}"})
708
- end
686
+ pagination_msg = options[:phrase] ? "Viewing most recent %{size} of %{total} commands matching '#{options[:phrase]}'" : "Viewing most recent %{size} of %{total} commands"
687
+ print_results_pagination(history_result[:meta], {:message =>pagination_msg})
709
688
  print reset, "\n"
710
689
  else
711
690
  print reset
@@ -73,15 +73,15 @@ class Morpheus::Cli::Snapshots
73
73
  "Name" => 'name',
74
74
  "Description" => 'description',
75
75
  "External Id" => 'externalId',
76
- "Status" => 'status',
77
- "State" => 'state',
76
+ # "State" => 'state',
78
77
  "Snapshot Type" => 'snapshotType',
79
- "Snapshot Created" => 'snapshotCreated',
80
- "Cloud" => 'zone.name',
81
- "Datastore" => 'datastore',
82
- "Parent Snapshot" => 'parentSnapshot',
83
- "Active" => 'currentlyActive',
84
- "Date Created" => 'dateCreated'
78
+ "Date Created" => lambda {|it| format_local_dt(it['snapshotCreated']) },
79
+ "Cloud" => lambda {|it| format_name_and_id(it['zone']) },
80
+ "Datastore" => lambda {|it| format_name_and_id(it['datastore']) },
81
+ "Parent Snapshot" => lambda {|it| format_name_and_id(it['parentSnapshot']) },
82
+ "Active" => lambda {|it| format_boolean(it['currentlyActive']) },
83
+ "Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
84
+ "Status" => lambda {|it| format_snapshot_status(it) }
85
85
  }
86
86
  print_description_list(description_cols, snapshot)
87
87
 
@@ -134,4 +134,20 @@ class Morpheus::Cli::Snapshots
134
134
  exit 1
135
135
  end
136
136
  end
137
+
138
+ protected
139
+
140
+ def format_snapshot_status(snapshot, return_color=cyan)
141
+ out = ""
142
+ status_string = snapshot['status'].to_s
143
+ if status_string == 'complete'
144
+ out << "#{green}#{status_string.upcase}#{return_color}"
145
+ elsif status_string == 'failed'
146
+ out << "#{red}#{status_string.upcase}#{return_color}"
147
+ else
148
+ out << "#{cyan}#{status_string.upcase}#{return_color}"
149
+ end
150
+ out
151
+ end
152
+
137
153
  end