morpheus-cli 4.2.8 → 4.2.10
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.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api.rb +1 -1
- data/lib/morpheus/api/activity_interface.rb +9 -0
- data/lib/morpheus/api/api_client.rb +83 -27
- data/lib/morpheus/api/apps_interface.rb +21 -0
- data/lib/morpheus/api/dashboard_interface.rb +5 -21
- data/lib/morpheus/api/instances_interface.rb +3 -10
- data/lib/morpheus/api/invoice_line_items_interface.rb +14 -0
- data/lib/morpheus/api/invoices_interface.rb +7 -12
- data/lib/morpheus/api/library_layouts_interface.rb +8 -0
- data/lib/morpheus/api/ping_interface.rb +20 -0
- data/lib/morpheus/api/projects_interface.rb +33 -0
- data/lib/morpheus/api/setup_interface.rb +19 -36
- data/lib/morpheus/api/user_settings_interface.rb +0 -6
- data/lib/morpheus/api/whoami_interface.rb +4 -8
- data/lib/morpheus/benchmarking.rb +16 -26
- data/lib/morpheus/cli.rb +10 -5
- data/lib/morpheus/cli/access_token_command.rb +5 -8
- data/lib/morpheus/cli/activity_command.rb +146 -0
- data/lib/morpheus/cli/apps.rb +312 -121
- data/lib/morpheus/cli/archives_command.rb +1 -1
- data/lib/morpheus/cli/auth_command.rb +4 -11
- data/lib/morpheus/cli/blueprints_command.rb +196 -137
- data/lib/morpheus/cli/change_password_command.rb +1 -1
- data/lib/morpheus/cli/cli_command.rb +225 -72
- data/lib/morpheus/cli/cli_registry.rb +2 -2
- data/lib/morpheus/cli/cloud_datastores_command.rb +1 -1
- data/lib/morpheus/cli/clouds.rb +5 -20
- data/lib/morpheus/cli/clusters.rb +4 -28
- data/lib/morpheus/cli/commands/standard/alias_command.rb +2 -9
- data/lib/morpheus/cli/commands/standard/benchmark_command.rb +2 -0
- data/lib/morpheus/cli/commands/standard/curl_command.rb +2 -3
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -6
- data/lib/morpheus/cli/commands/standard/man_command.rb +10 -7
- data/lib/morpheus/cli/commands/standard/ssl_verification_command.rb +10 -9
- data/lib/morpheus/cli/containers_command.rb +3 -3
- data/lib/morpheus/cli/credentials.rb +13 -16
- data/lib/morpheus/cli/error_handler.rb +18 -12
- data/lib/morpheus/cli/errors.rb +45 -0
- data/lib/morpheus/cli/execute_schedules_command.rb +1 -1
- data/lib/morpheus/cli/execution_request_command.rb +4 -4
- data/lib/morpheus/cli/groups.rb +84 -132
- data/lib/morpheus/cli/hosts.rb +6 -16
- data/lib/morpheus/cli/instances.rb +100 -183
- data/lib/morpheus/cli/invoices_command.rb +505 -71
- data/lib/morpheus/cli/library_layouts_command.rb +254 -166
- data/lib/morpheus/cli/library_option_lists_command.rb +0 -87
- data/lib/morpheus/cli/library_option_types_command.rb +0 -96
- data/lib/morpheus/cli/license.rb +3 -0
- data/lib/morpheus/cli/login.rb +17 -37
- data/lib/morpheus/cli/logout.rb +9 -5
- data/lib/morpheus/cli/mixins/accounts_helper.rb +83 -7
- data/lib/morpheus/cli/mixins/operations_helper.rb +41 -0
- data/lib/morpheus/cli/mixins/option_source_helper.rb +255 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +18 -4
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +222 -13
- data/lib/morpheus/cli/mixins/remote_helper.rb +139 -0
- data/lib/morpheus/cli/monitoring_checks_command.rb +11 -3
- data/lib/morpheus/cli/network_groups_command.rb +8 -2
- data/lib/morpheus/cli/option_types.rb +1 -1
- data/lib/morpheus/cli/ping.rb +252 -0
- data/lib/morpheus/cli/price_sets_command.rb +16 -27
- data/lib/morpheus/cli/prices_command.rb +34 -27
- data/lib/morpheus/cli/processes_command.rb +81 -7
- data/lib/morpheus/cli/projects_command.rb +607 -0
- data/lib/morpheus/cli/recent_activity_command.rb +87 -65
- data/lib/morpheus/cli/remote.rb +965 -974
- data/lib/morpheus/cli/reports_command.rb +3 -15
- data/lib/morpheus/cli/roles.rb +8 -31
- data/lib/morpheus/cli/service_plans_command.rb +25 -31
- data/lib/morpheus/cli/setup.rb +392 -0
- data/lib/morpheus/cli/shell.rb +144 -56
- data/lib/morpheus/cli/subnets_command.rb +71 -11
- data/lib/morpheus/cli/tasks.rb +3 -3
- data/lib/morpheus/cli/user_sources_command.rb +4 -4
- data/lib/morpheus/cli/users.rb +135 -109
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whitelabel_settings_command.rb +7 -7
- data/lib/morpheus/cli/whoami.rb +90 -129
- data/lib/morpheus/cli/wiki_command.rb +2 -14
- data/lib/morpheus/ext/rest_client.rb +36 -0
- data/lib/morpheus/formatters.rb +42 -5
- data/lib/morpheus/rest_client.rb +0 -10
- data/lib/morpheus/terminal.rb +41 -1
- data/lib/morpheus/util.rb +24 -0
- metadata +16 -3
- data/lib/morpheus/cli/command_error.rb +0 -22
|
@@ -65,7 +65,7 @@ class Morpheus::Cli::ChangePasswordCommand
|
|
|
65
65
|
raise_command_error "No current appliance, see `remote use`."
|
|
66
66
|
end
|
|
67
67
|
if !@current_remote[:username]
|
|
68
|
-
raise_command_error "You are not currently logged in to #{@current_remote[:name]
|
|
68
|
+
raise_command_error "You are not currently logged in to #{display_appliance(@current_remote[:name], @current_remote[:url])}"
|
|
69
69
|
end
|
|
70
70
|
username = @current_remote[:username]
|
|
71
71
|
end
|
|
@@ -97,8 +97,12 @@ module Morpheus
|
|
|
97
97
|
@no_prompt != true
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
def raise_command_error(msg)
|
|
101
|
-
raise Morpheus::Cli::CommandError.new(msg)
|
|
100
|
+
def raise_command_error(msg, args=[], optparse=nil, exit_code=nil)
|
|
101
|
+
raise Morpheus::Cli::CommandError.new(msg, args, optparse, exit_code)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def raise_args_error(msg, args=[], optparse=nil, exit_code=nil)
|
|
105
|
+
raise Morpheus::Cli::CommandArgumentsError.new(msg, args, optparse, exit_code)
|
|
102
106
|
end
|
|
103
107
|
|
|
104
108
|
# parse_id_list splits returns the given id_list with its values split on a comma
|
|
@@ -128,6 +132,11 @@ module Morpheus
|
|
|
128
132
|
raise_command_error "Invalid value for #{option} option"
|
|
129
133
|
end
|
|
130
134
|
|
|
135
|
+
# this returns all the options passed in by -O, parsed all nicely into objects.
|
|
136
|
+
def parse_passed_options(options)
|
|
137
|
+
passed_options = options[:options] ? options[:options].reject {|k,v| k.is_a?(Symbol) } : {}
|
|
138
|
+
return passed_options
|
|
139
|
+
end
|
|
131
140
|
# Appends Array of OptionType definitions to an OptionParser instance
|
|
132
141
|
# This adds an option like --fieldContext.fieldName="VALUE"
|
|
133
142
|
# @param opts [OptionParser]
|
|
@@ -216,24 +225,39 @@ module Morpheus
|
|
|
216
225
|
opts
|
|
217
226
|
end
|
|
218
227
|
|
|
219
|
-
|
|
220
|
-
build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :dry_run, :remote] + includes, excludes)
|
|
221
|
-
end
|
|
228
|
+
## the standard options for a command that makes api requests (most of them)
|
|
222
229
|
|
|
223
230
|
def build_standard_get_options(opts, options, includes=[], excludes=[])
|
|
224
|
-
build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :dry_run, :remote] + includes, excludes)
|
|
231
|
+
build_common_options(opts, options, [:query, :json, :yaml, :csv, :fields, :quiet, :dry_run, :remote] + includes, excludes)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def build_standard_post_options(opts, options, includes=[], excludes=[])
|
|
235
|
+
build_common_options(opts, options, [:options, :payload, :json, :quiet, :dry_run, :remote] + includes, excludes)
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def build_standard_put_options(opts, options, includes=[], excludes=[])
|
|
239
|
+
build_standard_post_options(opts, options, includes, excludes)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def build_standard_delete_options(opts, options, includes=[], excludes=[])
|
|
243
|
+
build_common_options(opts, options, [:auto_confirm, :query, :json, :quiet, :dry_run, :remote] + includes, excludes)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# list is GET that supports phrase,max,offset,sort,direction
|
|
247
|
+
def build_standard_list_options(opts, options, includes=[], excludes=[])
|
|
248
|
+
build_standard_get_options(opts, options, [:list] + includes, excludes=[])
|
|
225
249
|
end
|
|
226
250
|
|
|
227
251
|
def build_standard_add_options(opts, options, includes=[], excludes=[])
|
|
228
|
-
|
|
252
|
+
build_standard_post_options(opts, options, includes, excludes)
|
|
229
253
|
end
|
|
230
254
|
|
|
231
255
|
def build_standard_update_options(opts, options, includes=[], excludes=[])
|
|
232
|
-
|
|
256
|
+
build_standard_put_options(opts, options, includes, excludes)
|
|
233
257
|
end
|
|
234
258
|
|
|
235
259
|
def build_standard_remove_options(opts, options, includes=[], excludes=[])
|
|
236
|
-
|
|
260
|
+
build_standard_delete_options(opts, options, includes, excludes)
|
|
237
261
|
end
|
|
238
262
|
|
|
239
263
|
# appends to the passed OptionParser all the generic options
|
|
@@ -494,12 +518,33 @@ module Morpheus
|
|
|
494
518
|
opts.on( '-T', '--token TOKEN', "Access token for authentication with --remote. Saved credentials are used by default." ) do |val|
|
|
495
519
|
options[:remote_token] = val
|
|
496
520
|
end unless excludes.include?(:remote_token)
|
|
521
|
+
opts.on( '--token-file FILE', String, "Token File, read a file containing the access token." ) do |val|
|
|
522
|
+
token_file = File.expand_path(val)
|
|
523
|
+
if !File.exists?(token_file) || !File.file?(token_file)
|
|
524
|
+
raise ::OptionParser::InvalidOption.new("File not found: #{token_file}")
|
|
525
|
+
end
|
|
526
|
+
options[:remote_token] = File.read(token_file).to_s.split("\n").first.strip
|
|
527
|
+
end
|
|
528
|
+
opts.add_hidden_option('--token-file') if opts.is_a?(Morpheus::Cli::OptionParser)
|
|
497
529
|
opts.on( '-U', '--username USERNAME', "Username for authentication." ) do |val|
|
|
498
530
|
options[:remote_username] = val
|
|
499
531
|
end unless excludes.include?(:remote_username)
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
unless excludes.include?(:remote_password)
|
|
535
|
+
opts.on( '-P', '--password PASSWORD', "Password for authentication." ) do |val|
|
|
536
|
+
options[:remote_password] = val
|
|
537
|
+
end
|
|
538
|
+
opts.on( '--password-file FILE', String, "Password File, read a file containing the password for authentication." ) do |val|
|
|
539
|
+
password_file = File.expand_path(val)
|
|
540
|
+
if !File.exists?(password_file) || !File.file?(password_file)
|
|
541
|
+
raise ::OptionParser::InvalidOption.new("File not found: #{password_file}")
|
|
542
|
+
end
|
|
543
|
+
file_content = File.read(password_file) #.strip
|
|
544
|
+
options[:remote_password] = File.read(password_file).to_s.split("\n").first
|
|
545
|
+
end
|
|
546
|
+
opts.add_hidden_option('--password-file') if opts.is_a?(Morpheus::Cli::OptionParser)
|
|
547
|
+
end
|
|
503
548
|
|
|
504
549
|
# todo: also require this for talking to plain old HTTP
|
|
505
550
|
opts.on('-I','--insecure', "Allow insecure HTTPS communication. i.e. bad SSL certificate.") do |val|
|
|
@@ -622,7 +667,7 @@ module Morpheus
|
|
|
622
667
|
end
|
|
623
668
|
#opts.add_hidden_option('--all-fields') if opts.is_a?(Morpheus::Cli::OptionParser)
|
|
624
669
|
opts.on(nil, '--wrap', "Wrap table columns instead hiding them when terminal is not wide enough.") do
|
|
625
|
-
options[:
|
|
670
|
+
options[:wrap] = true
|
|
626
671
|
end
|
|
627
672
|
when :thin
|
|
628
673
|
opts.on( '--thin', '--thin', "Format headers and columns with thin borders." ) do |val|
|
|
@@ -701,7 +746,8 @@ module Morpheus
|
|
|
701
746
|
|
|
702
747
|
|
|
703
748
|
# Benchmark this command?
|
|
704
|
-
|
|
749
|
+
# Also useful for seeing exit status for every command.
|
|
750
|
+
opts.on('-B','--benchmark', "Print benchmark time and exit/error after the command is finished.") do
|
|
705
751
|
options[:benchmark] = true
|
|
706
752
|
# this is hacky, but working!
|
|
707
753
|
# shell handles returning to false
|
|
@@ -725,6 +771,15 @@ module Morpheus
|
|
|
725
771
|
# end
|
|
726
772
|
end
|
|
727
773
|
|
|
774
|
+
# A way to ensure debugging is off, it should go back on after the command is complete.
|
|
775
|
+
opts.on('--no-debug','--no-debug', "Disable debugging.") do
|
|
776
|
+
options[:debug] = false
|
|
777
|
+
Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::INFO)
|
|
778
|
+
::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
|
|
779
|
+
end
|
|
780
|
+
opts.add_hidden_option('--no-debug') if opts.is_a?(Morpheus::Cli::OptionParser)
|
|
781
|
+
|
|
782
|
+
|
|
728
783
|
opts.on('-h', '--help', "Print this help" ) do
|
|
729
784
|
puts opts
|
|
730
785
|
exit # return 0 maybe?
|
|
@@ -741,6 +796,10 @@ module Morpheus
|
|
|
741
796
|
self.class.subcommands
|
|
742
797
|
end
|
|
743
798
|
|
|
799
|
+
def visible_subcommands
|
|
800
|
+
self.class.visible_subcommands
|
|
801
|
+
end
|
|
802
|
+
|
|
744
803
|
def subcommand_aliases
|
|
745
804
|
self.class.subcommand_aliases
|
|
746
805
|
end
|
|
@@ -821,10 +880,8 @@ module Morpheus
|
|
|
821
880
|
end
|
|
822
881
|
cmd_method = subcommands[subcommand_name]
|
|
823
882
|
if !cmd_method
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
puts_error "'#{subcommand_name}' is not recognized.\n#{full_command_usage}"
|
|
827
|
-
return 127
|
|
883
|
+
error_msg = "'#{command_name} #{subcommand_name}' is not a morpheus command.\n#{full_command_usage}"
|
|
884
|
+
raise CommandNotFoundError.new(error_msg)
|
|
828
885
|
end
|
|
829
886
|
self.send(cmd_method, args[1..-1])
|
|
830
887
|
end
|
|
@@ -857,96 +914,129 @@ module Morpheus
|
|
|
857
914
|
return failed_result ? failed_result : cmd_results.last
|
|
858
915
|
end
|
|
859
916
|
|
|
917
|
+
# def connect(options={})
|
|
918
|
+
# Morpheus::Logging::DarkPrinter.puts "#{command_name} has not defined connect()" if Morpheus::Logging.debug?
|
|
919
|
+
# end
|
|
920
|
+
|
|
860
921
|
# This supports the simple remote option eg. `instances add --remote "qa"`
|
|
861
922
|
# It will establish a connection to the pre-configured appliance named "qa"
|
|
862
|
-
#
|
|
863
|
-
# Otherwise, the current active appliance is used...
|
|
923
|
+
# By default it will connect to the active (current) remote appliance
|
|
864
924
|
# This returns a new instance of Morpheus::APIClient (and sets @access_token, and @appliance)
|
|
865
925
|
# Your command should be ready to make api requests after this.
|
|
926
|
+
# This will prompt for credentials if none are found, use :skip_login
|
|
927
|
+
# Credentials will be saved unless --remote-url or --token is being used.
|
|
866
928
|
def establish_remote_appliance_connection(options)
|
|
867
929
|
# todo: probably refactor and don't rely on this method to set these instance vars
|
|
930
|
+
@remote_appliance = nil
|
|
868
931
|
@appliance_name, @appliance_url, @access_token = nil, nil, nil
|
|
869
932
|
@api_client = nil
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
if options[:
|
|
933
|
+
@do_save_credentials = true
|
|
934
|
+
# skip saving if --remote-url or --username or --password are passed in
|
|
935
|
+
if options[:remote_url] || options[:remote_token] || options[:remote_username] || options[:remote_password]
|
|
936
|
+
@do_save_credentials = false
|
|
937
|
+
end
|
|
938
|
+
appliance = nil
|
|
939
|
+
if options[:remote_url]
|
|
940
|
+
# --remote-url means use an arbitrary url, do not save any appliance config
|
|
941
|
+
# appliance = {name:'remote-url', url:options[:remote_url]}
|
|
942
|
+
appliance = {url:options[:remote_url]}
|
|
943
|
+
appliance[:temporary] = true
|
|
944
|
+
#appliance[:status] = "ready" # or "unknown"
|
|
945
|
+
# appliance[:last_check] = nil
|
|
946
|
+
elsif options[:remote]
|
|
947
|
+
# --remote means use the specified remote
|
|
873
948
|
appliance = ::Morpheus::Cli::Remote.load_remote(options[:remote])
|
|
874
|
-
if
|
|
949
|
+
if appliance.nil?
|
|
875
950
|
if ::Morpheus::Cli::Remote.appliances.empty?
|
|
876
|
-
raise_command_error "
|
|
951
|
+
raise_command_error "No remote appliances exist, see the command `remote add`."
|
|
877
952
|
else
|
|
878
|
-
raise_command_error "Remote appliance not found by the name '#{options[:remote]}'"
|
|
953
|
+
raise_command_error "Remote appliance not found by the name '#{options[:remote]}', see `remote list`"
|
|
879
954
|
end
|
|
880
955
|
end
|
|
881
956
|
else
|
|
957
|
+
# use active remote
|
|
882
958
|
appliance = ::Morpheus::Cli::Remote.load_active_remote()
|
|
883
959
|
if !appliance
|
|
884
960
|
if ::Morpheus::Cli::Remote.appliances.empty?
|
|
885
|
-
raise_command_error "
|
|
961
|
+
raise_command_error "No remote appliances exist, see the command `remote add`"
|
|
886
962
|
else
|
|
887
|
-
raise_command_error "
|
|
963
|
+
raise_command_error "#{command_name} requires a remote to be specified, try the option -r [remote] or see the command `remote use`"
|
|
888
964
|
end
|
|
889
965
|
end
|
|
890
966
|
end
|
|
967
|
+
@remote_appliance = appliance
|
|
891
968
|
@appliance_name = appliance[:name]
|
|
892
|
-
@appliance_url = appliance[:
|
|
893
|
-
|
|
969
|
+
@appliance_url = appliance[:url] || appliance[:host] # it used to store :host in the YAML
|
|
970
|
+
# set enable_ssl_verification
|
|
894
971
|
# instead of toggling this global value
|
|
895
972
|
# this should just be an attribute of the api client
|
|
896
973
|
# for now, this fixes the issue where passing --insecure or --remote
|
|
897
974
|
# would then apply to all subsequent commands...
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
end
|
|
975
|
+
allow_insecure = false
|
|
976
|
+
if options[:insecure] || appliance[:insecure] || Morpheus::Cli::Shell.insecure
|
|
977
|
+
allow_insecure = true
|
|
978
|
+
end
|
|
979
|
+
# Morpheus::RestClient.enable_ssl_verification = allow_insecure != true
|
|
980
|
+
if allow_insecure && Morpheus::RestClient.ssl_verification_enabled?
|
|
981
|
+
Morpheus::RestClient.enable_ssl_verification = false
|
|
982
|
+
elsif !allow_insecure && !Morpheus::RestClient.ssl_verification_enabled?
|
|
983
|
+
Morpheus::RestClient.enable_ssl_verification = true
|
|
908
984
|
end
|
|
909
985
|
|
|
910
|
-
#
|
|
986
|
+
# always support accepting --username and --password on the command line
|
|
911
987
|
# it's probably better not to do that tho, just so it stays out of history files
|
|
912
|
-
|
|
913
988
|
|
|
914
989
|
# if !@appliance_name && !@appliance_url
|
|
915
990
|
# raise_command_error "Please specify a remote appliance with -r or see the command `remote use`"
|
|
916
991
|
# end
|
|
917
992
|
|
|
918
|
-
Morpheus::Logging::DarkPrinter.puts "establishing connection to
|
|
919
|
-
#puts "#{dark} #=> establishing connection to [#{@appliance_name}] #{@appliance_url}#{reset}\n" if options[:debug]
|
|
993
|
+
Morpheus::Logging::DarkPrinter.puts "establishing connection to remote #{display_appliance(@appliance_name, @appliance_url)}" if Morpheus::Logging.debug?
|
|
920
994
|
|
|
995
|
+
if options[:no_authorization]
|
|
996
|
+
# maybe handle this here..
|
|
997
|
+
options[:skip_login] = true
|
|
998
|
+
options[:skip_verify_access_token] = true
|
|
999
|
+
end
|
|
921
1000
|
|
|
922
1001
|
# ok, get some credentials.
|
|
923
|
-
#
|
|
924
|
-
#
|
|
925
|
-
# passing --
|
|
1002
|
+
# use saved credentials by default or prompts for username, password.
|
|
1003
|
+
# passing --remote-url will skip loading saved credentials and prompt for login to use with the url
|
|
1004
|
+
# passing --token skips login prompting and uses the provided token.
|
|
1005
|
+
# passing --token or --username will skip saving credentials to appliance config, they are just used for one command
|
|
1006
|
+
# ideally this should not prompt now and wait until the client is used on a protected endpoint.
|
|
1007
|
+
# @wallet = nil
|
|
926
1008
|
if options[:remote_token]
|
|
927
|
-
@
|
|
1009
|
+
@wallet = {'access_token' => options[:remote_token]} #'username' => 'anonymous'
|
|
1010
|
+
elsif options[:remote_url]
|
|
1011
|
+
credentials = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url)
|
|
1012
|
+
unless options[:skip_login]
|
|
1013
|
+
@wallet = credentials.request_credentials(options, @do_save_credentials)
|
|
1014
|
+
end
|
|
928
1015
|
else
|
|
929
1016
|
credentials = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url)
|
|
930
|
-
#
|
|
931
|
-
|
|
932
|
-
if options[:remote_token]
|
|
933
|
-
@wallet = credentials.request_credentials(options, false)
|
|
934
|
-
elsif options[:remote_url] || options[:remote_username]
|
|
935
|
-
@wallet = credentials.request_credentials(options, false)
|
|
936
|
-
else
|
|
937
|
-
#@wallet = credentials.request_credentials(options)
|
|
1017
|
+
# use saved credentials unless --username or passed
|
|
1018
|
+
unless options[:remote_username]
|
|
938
1019
|
@wallet = credentials.load_saved_credentials()
|
|
939
1020
|
end
|
|
940
|
-
|
|
941
|
-
#
|
|
942
|
-
#
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1021
|
+
# using active remote OR --remote flag
|
|
1022
|
+
# used saved credentials or login
|
|
1023
|
+
# ideally this sould not prompt now and wait until the client is used on a protected endpoint.
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
if @wallet.nil? || @wallet['access_token'].nil?
|
|
1027
|
+
unless options[:skip_login]
|
|
1028
|
+
@wallet = credentials.request_credentials(options, @do_save_credentials)
|
|
1029
|
+
end
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
end
|
|
1033
|
+
@access_token = @wallet ? @wallet['access_token'] : nil
|
|
1034
|
+
|
|
1035
|
+
# validate we have a token
|
|
1036
|
+
# hrm...
|
|
1037
|
+
unless options[:skip_verify_access_token]
|
|
1038
|
+
if @access_token.empty?
|
|
1039
|
+
raise AuthorizationRequiredError.new("Failed to acquire access token for #{display_appliance(@appliance_name, @appliance_url)}. Verify your credentials are correct.")
|
|
950
1040
|
end
|
|
951
1041
|
end
|
|
952
1042
|
|
|
@@ -956,9 +1046,29 @@ module Morpheus
|
|
|
956
1046
|
return api_client
|
|
957
1047
|
end
|
|
958
1048
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1049
|
+
# verify_args! verifies that the right number of commands were passed
|
|
1050
|
+
# and raises a command error if not.
|
|
1051
|
+
# Example: verify_args!(args:args, count:1, optparse:optparse)
|
|
1052
|
+
# this could go be done in optparse.parse instead perhaps
|
|
1053
|
+
def verify_args!(opts={})
|
|
1054
|
+
args = opts[:args] || []
|
|
1055
|
+
if opts[:count]
|
|
1056
|
+
if args.count < opts[:count]
|
|
1057
|
+
raise_args_error("not enough arguments, expected #{opts[:count]} and got #{args.count == 0 ? '0' : args.count.to_s + ': '}#{args.join(', ')}", args, opts[:optparse])
|
|
1058
|
+
elsif args.count > opts[:count]
|
|
1059
|
+
raise_args_error("too many arguments, expected #{opts[:count]} and got #{args.count == 0 ? '0' : args.count.to_s + ': '}#{args.join(', ')}", args, opts[:optparse])
|
|
1060
|
+
end
|
|
1061
|
+
else
|
|
1062
|
+
if opts[:min]
|
|
1063
|
+
if args.count < opts[:min]
|
|
1064
|
+
raise_args_error("not many arguments, expected #{opts[:min] || '0'}-#{opts[:max] || 'N'} and got #{args.count == 0 ? '0' : args.count.to_s + ': '}#{args.join(', ')}", args, opts[:optparse])
|
|
1065
|
+
end
|
|
1066
|
+
end
|
|
1067
|
+
if opts[:max]
|
|
1068
|
+
if args.count > opts[:max]
|
|
1069
|
+
raise_args_error("too many arguments, expected #{opts[:min] || '0'}-#{opts[:max] || 'N'} and got #{args.count == 0 ? '0' : args.count.to_s + ': '}#{args.join(', ')}", args, opts[:optparse])
|
|
1070
|
+
end
|
|
1071
|
+
end
|
|
962
1072
|
end
|
|
963
1073
|
true
|
|
964
1074
|
end
|
|
@@ -1042,9 +1152,22 @@ module Morpheus
|
|
|
1042
1152
|
payload
|
|
1043
1153
|
end
|
|
1044
1154
|
|
|
1045
|
-
|
|
1155
|
+
def render_response(json_response, options, object_key=nil, &block)
|
|
1156
|
+
render_result = render_with_format(json_response, options, object_key)
|
|
1157
|
+
if render_result
|
|
1158
|
+
return 0, nil
|
|
1159
|
+
else
|
|
1160
|
+
if block_given?
|
|
1161
|
+
return yield
|
|
1162
|
+
else
|
|
1163
|
+
return 0, nil
|
|
1164
|
+
end
|
|
1165
|
+
end
|
|
1166
|
+
end
|
|
1167
|
+
|
|
1168
|
+
# basic rendering for options :json, :yml, :csv, :quiet, and :outfile
|
|
1046
1169
|
# returns the string rendered, or nil if nothing was rendered.
|
|
1047
|
-
def render_with_format(json_response, options, object_key=nil)
|
|
1170
|
+
def render_with_format(json_response, options, object_key=nil, &block)
|
|
1048
1171
|
output = nil
|
|
1049
1172
|
if options[:json]
|
|
1050
1173
|
output = as_json(json_response, options, object_key)
|
|
@@ -1060,7 +1183,7 @@ module Morpheus
|
|
|
1060
1183
|
elsif options[:quiet]
|
|
1061
1184
|
# note: returning non nil means the calling function knows to return rght away.. kinda weird..
|
|
1062
1185
|
# but means we need less if options[:quiet] blocks in every action.
|
|
1063
|
-
|
|
1186
|
+
return ""
|
|
1064
1187
|
end
|
|
1065
1188
|
if output
|
|
1066
1189
|
if options[:outfile]
|
|
@@ -1068,6 +1191,17 @@ module Morpheus
|
|
|
1068
1191
|
else
|
|
1069
1192
|
puts output
|
|
1070
1193
|
end
|
|
1194
|
+
else
|
|
1195
|
+
if block_given?
|
|
1196
|
+
# invoke the user given block to render (print output)
|
|
1197
|
+
# hope it returned something well formed, there's a parse method for that..
|
|
1198
|
+
cmd_render_result = yield
|
|
1199
|
+
# could try to support writing output to options[:outfile] here too..
|
|
1200
|
+
# output is already printed inside block though
|
|
1201
|
+
# if cmd_render_result
|
|
1202
|
+
# return output
|
|
1203
|
+
# end
|
|
1204
|
+
end
|
|
1071
1205
|
end
|
|
1072
1206
|
return output
|
|
1073
1207
|
end
|
|
@@ -1099,6 +1233,14 @@ module Morpheus
|
|
|
1099
1233
|
!!@hidden_command
|
|
1100
1234
|
end
|
|
1101
1235
|
|
|
1236
|
+
def set_subcommands_hidden(*cmds)
|
|
1237
|
+
@hidden_subcommands ||= []
|
|
1238
|
+
cmds.flatten.each do |cmd|
|
|
1239
|
+
@hidden_subcommands << cmd.to_sym
|
|
1240
|
+
end
|
|
1241
|
+
@hidden_subcommands
|
|
1242
|
+
end
|
|
1243
|
+
|
|
1102
1244
|
def command_description
|
|
1103
1245
|
@command_description
|
|
1104
1246
|
end
|
|
@@ -1153,6 +1295,17 @@ module Morpheus
|
|
|
1153
1295
|
@subcommands ||= {}
|
|
1154
1296
|
end
|
|
1155
1297
|
|
|
1298
|
+
def visible_subcommands
|
|
1299
|
+
cmds = subcommands.clone
|
|
1300
|
+
if @hidden_subcommands && !@hidden_subcommands.empty?
|
|
1301
|
+
@hidden_subcommands.each do |hidden_cmd|
|
|
1302
|
+
cmds.delete(hidden_cmd.to_s)
|
|
1303
|
+
cmds.delete(hidden_cmd.to_sym)
|
|
1304
|
+
end
|
|
1305
|
+
end
|
|
1306
|
+
cmds
|
|
1307
|
+
end
|
|
1308
|
+
|
|
1156
1309
|
def has_subcommand?(cmd_name)
|
|
1157
1310
|
return false if cmd_name.empty?
|
|
1158
1311
|
@subcommands && @subcommands[cmd_name.to_s]
|