morpheus-cli 3.6.8 → 3.6.9

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 (93) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/account_groups_interface.rb +2 -2
  3. data/lib/morpheus/api/accounts_interface.rb +4 -7
  4. data/lib/morpheus/api/api_client.rb +207 -70
  5. data/lib/morpheus/api/app_templates_interface.rb +7 -28
  6. data/lib/morpheus/api/apps_interface.rb +14 -21
  7. data/lib/morpheus/api/archive_buckets_interface.rb +2 -2
  8. data/lib/morpheus/api/archive_files_interface.rb +6 -6
  9. data/lib/morpheus/api/auth_interface.rb +14 -1
  10. data/lib/morpheus/api/blueprints_interface.rb +9 -16
  11. data/lib/morpheus/api/cloud_datastores_interface.rb +1 -1
  12. data/lib/morpheus/api/cloud_policies_interface.rb +1 -1
  13. data/lib/morpheus/api/clouds_interface.rb +18 -21
  14. data/lib/morpheus/api/cypher_interface.rb +19 -28
  15. data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
  16. data/lib/morpheus/api/group_policies_interface.rb +1 -1
  17. data/lib/morpheus/api/groups_interface.rb +4 -4
  18. data/lib/morpheus/api/image_builder_boot_scripts_interface.rb +1 -1
  19. data/lib/morpheus/api/image_builder_image_builds_interface.rb +2 -2
  20. data/lib/morpheus/api/image_builder_preseed_scripts_interface.rb +1 -1
  21. data/lib/morpheus/api/instances_interface.rb +17 -23
  22. data/lib/morpheus/api/logs_interface.rb +7 -10
  23. data/lib/morpheus/api/network_domains_interface.rb +1 -1
  24. data/lib/morpheus/api/network_groups_interface.rb +1 -1
  25. data/lib/morpheus/api/network_pool_servers_interface.rb +1 -1
  26. data/lib/morpheus/api/network_pools_interface.rb +1 -1
  27. data/lib/morpheus/api/network_proxies_interface.rb +1 -1
  28. data/lib/morpheus/api/network_services_interface.rb +1 -1
  29. data/lib/morpheus/api/networks_interface.rb +1 -1
  30. data/lib/morpheus/api/old_cypher_interface.rb +55 -0
  31. data/lib/morpheus/api/packages_interface.rb +1 -1
  32. data/lib/morpheus/api/policies_interface.rb +1 -1
  33. data/lib/morpheus/api/setup_interface.rb +1 -1
  34. data/lib/morpheus/api/storage_providers_interface.rb +1 -1
  35. data/lib/morpheus/api/whoami_interface.rb +1 -1
  36. data/lib/morpheus/benchmarking.rb +277 -0
  37. data/lib/morpheus/cli.rb +6 -22
  38. data/lib/morpheus/cli/access_token_command.rb +172 -0
  39. data/lib/morpheus/cli/accounts.rb +5 -0
  40. data/lib/morpheus/cli/apps.rb +93 -37
  41. data/lib/morpheus/cli/archives_command.rb +0 -2
  42. data/lib/morpheus/cli/auth_command.rb +112 -0
  43. data/lib/morpheus/cli/blueprints_command.rb +50 -13
  44. data/lib/morpheus/cli/change_password_command.rb +148 -0
  45. data/lib/morpheus/cli/cli_command.rb +173 -49
  46. data/lib/morpheus/cli/clouds.rb +15 -5
  47. data/lib/morpheus/cli/command_error.rb +7 -1
  48. data/lib/morpheus/cli/{alias_command.rb → commands/standard/alias_command.rb} +79 -51
  49. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +399 -0
  50. data/lib/morpheus/cli/commands/standard/coloring_command.rb +60 -0
  51. data/lib/morpheus/cli/{curl_command.rb → commands/standard/curl_command.rb} +0 -7
  52. data/lib/morpheus/cli/commands/standard/debug_command.rb +61 -0
  53. data/lib/morpheus/cli/{echo_command.rb → commands/standard/echo_command.rb} +1 -1
  54. data/lib/morpheus/cli/{edit_profile_command.rb → commands/standard/edit_profile_command.rb} +0 -0
  55. data/lib/morpheus/cli/{edit_rc_command.rb → commands/standard/edit_rc_command.rb} +0 -0
  56. data/lib/morpheus/cli/commands/standard/get_prompt_command.rb +39 -0
  57. data/lib/morpheus/cli/commands/standard/history_command.rb +76 -0
  58. data/lib/morpheus/cli/{log_level_command.rb → commands/standard/log_level_command.rb} +1 -1
  59. data/lib/morpheus/cli/{man_command.rb → commands/standard/man_command.rb} +2 -2
  60. data/lib/morpheus/cli/commands/standard/rm_command.rb +14 -0
  61. data/lib/morpheus/cli/commands/standard/set_prompt_command.rb +54 -0
  62. data/lib/morpheus/cli/{sleep_command.rb → commands/standard/sleep_command.rb} +0 -0
  63. data/lib/morpheus/cli/{source_command.rb → commands/standard/source_command.rb} +0 -0
  64. data/lib/morpheus/cli/{ssl_verification_command.rb → commands/standard/ssl_verification_command.rb} +1 -1
  65. data/lib/morpheus/cli/commands/standard/tee_command.rb +14 -0
  66. data/lib/morpheus/cli/{version_command.rb → commands/standard/version_command.rb} +0 -0
  67. data/lib/morpheus/cli/credentials.rb +276 -87
  68. data/lib/morpheus/cli/cypher_command.rb +333 -214
  69. data/lib/morpheus/cli/error_handler.rb +12 -2
  70. data/lib/morpheus/cli/groups.rb +44 -20
  71. data/lib/morpheus/cli/hosts.rb +39 -16
  72. data/lib/morpheus/cli/instances.rb +114 -62
  73. data/lib/morpheus/cli/login.rb +74 -21
  74. data/lib/morpheus/cli/logout.rb +3 -4
  75. data/lib/morpheus/cli/mixins/accounts_helper.rb +50 -18
  76. data/lib/morpheus/cli/mixins/print_helper.rb +207 -42
  77. data/lib/morpheus/cli/old_cypher_command.rb +414 -0
  78. data/lib/morpheus/cli/option_parser.rb +6 -1
  79. data/lib/morpheus/cli/processes_command.rb +3 -0
  80. data/lib/morpheus/cli/remote.rb +11 -17
  81. data/lib/morpheus/cli/roles.rb +17 -17
  82. data/lib/morpheus/cli/security_groups.rb +47 -17
  83. data/lib/morpheus/cli/shell.rb +139 -79
  84. data/lib/morpheus/cli/tenants_command.rb +353 -0
  85. data/lib/morpheus/cli/users.rb +26 -18
  86. data/lib/morpheus/cli/version.rb +1 -1
  87. data/lib/morpheus/cli/whoami.rb +14 -10
  88. data/lib/morpheus/formatters.rb +4 -4
  89. data/lib/morpheus/logging.rb +16 -8
  90. data/lib/morpheus/terminal.rb +63 -34
  91. metadata +28 -15
  92. data/lib/morpheus/cli/coloring_command.rb +0 -45
  93. data/lib/morpheus/cli/set_prompt_command.rb +0 -51
@@ -0,0 +1,60 @@
1
+ require 'optparse'
2
+ require 'morpheus/cli/cli_command'
3
+ require 'json'
4
+
5
+ # This is for use in dotfile scripts
6
+ # It allows you to turn colors on or off globally
7
+ class Morpheus::Cli::ColoringCommand
8
+ include Morpheus::Cli::CliCommand
9
+ set_command_name :coloring
10
+ set_command_hidden
11
+
12
+ def handle(args)
13
+ append_newline = true
14
+ options = {}
15
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
16
+ opts.banner = "Usage: morpheus #{command_name} [on|off]"
17
+ #build_common_options(opts, options, [])
18
+ opts.on('-h', '--help', "Print this help" ) do
19
+ puts opts
20
+ exit
21
+ end
22
+ opts.footer = "Enable [on] or Disable [off] ANSI Colors for all output.\n" +
23
+ "Use [on?] or [off?] to print the current value and exit accordingly." + "\n" +
24
+ "Pass no arguments to just print the current value."
25
+ end
26
+ optparse.parse!(args)
27
+ if args.count > 1
28
+ raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
29
+ end
30
+
31
+ exit_code = 0
32
+
33
+ if args.count == 0
34
+ # just print
35
+ else
36
+ subcmd = args[0].to_s.strip
37
+ if subcmd == "on"
38
+ Term::ANSIColor::coloring = true
39
+ elsif subcmd == "off"
40
+ Term::ANSIColor::coloring = false
41
+ elsif subcmd == "on?"
42
+ exit_code = Term::ANSIColor::coloring? ? 0 : 1
43
+ elsif subcmd == "off?"
44
+ exit_code = Term::ANSIColor::coloring? ? 1 : 0
45
+ else
46
+ puts optparse
47
+ return 127
48
+ end
49
+ end
50
+ unless options[:quiet]
51
+ if Term::ANSIColor::coloring?
52
+ puts "#{cyan}coloring: #{bold}#{green}on#{reset}"
53
+ else
54
+ puts "coloring: off"
55
+ end
56
+ end
57
+ return exit_code
58
+ end
59
+
60
+ end
@@ -53,13 +53,6 @@ EOT
53
53
  curl_args.unshift "--inescure"
54
54
  end
55
55
 
56
- # @access_token = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials()
57
- # if !@access_token
58
- # print yellow,"You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}",reset,"\n"
59
- # print yellow,"Use the 'login' command.",reset,"\n"
60
- # return 0
61
- # end
62
-
63
56
  if !@appliance_url
64
57
  raise "Unable to determine remote appliance url"
65
58
  print "#{red}Unable to determine remote appliance url.#{reset}\n"
@@ -0,0 +1,61 @@
1
+ require 'morpheus/cli/cli_command'
2
+ require 'morpheus/logging'
3
+
4
+ # This is for use in dotfile scripts
5
+ # It allows you to turn colors on or off globally
6
+ class Morpheus::Cli::DebugCommand
7
+ include Morpheus::Cli::CliCommand
8
+ set_command_name :debug
9
+ set_command_hidden
10
+
11
+ def handle(args)
12
+ append_newline = true
13
+ options = {}
14
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
15
+ opts.banner = "Usage: morpheus #{command_name} [on|off]"
16
+ #build_common_options(opts, options, [])
17
+ opts.on('-h', '--help', "Print this help" ) do
18
+ puts opts
19
+ exit
20
+ end
21
+ opts.footer = "Enable [on] or Disable [off] debugging for all output.\n" +
22
+ "Use [on?] or [off?] to print the current value and exit accordingly." + "\n" +
23
+ "Pass no arguments to just print the current value."
24
+ end
25
+ optparse.parse!(args)
26
+ if args.count > 1
27
+ raise_command_error "wrong number of arguments, expected 0-1 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
28
+ end
29
+
30
+ exit_code = 0
31
+
32
+ if args.count == 0
33
+ # just print
34
+ else
35
+ subcmd = args[0].to_s.strip
36
+ if subcmd == "on"
37
+ Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
38
+ ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
39
+ elsif subcmd == "off"
40
+ Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::INFO)
41
+ ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
42
+ elsif subcmd == "on?"
43
+ exit_code = Morpheus::Logging.debug? ? 0 : 1
44
+ elsif subcmd == "off?"
45
+ exit_code = Morpheus::Logging.debug? ? 1 : 0
46
+ else
47
+ puts optparse
48
+ return 127
49
+ end
50
+ end
51
+ unless options[:quiet]
52
+ if Morpheus::Logging.debug?
53
+ puts "#{cyan}debug: #{green}on#{reset}"
54
+ else
55
+ puts "#{cyan}debug: #{dark}off#{reset}"
56
+ end
57
+ end
58
+ return exit_code
59
+ end
60
+
61
+ end
@@ -23,7 +23,7 @@ class Morpheus::Cli::Echo
23
23
  var_map.merge!(DEFAULT_VARIABLE_MAP)
24
24
  appliance = ::Morpheus::Cli::Remote.load_active_remote()
25
25
  if appliance
26
- var_map.merge!({'%remote' => appliance[:name], '%remote_url' => appliance[:host].to_s, '%username' => appliance[:username].to_s})
26
+ var_map.merge!({'%remote' => appliance[:name], '%remote_url' => (appliance[:host].to_s || appliance[:url].to_s), '%username' => appliance[:username].to_s})
27
27
  else
28
28
  var_map.merge!({'%remote' => '', '%remote_url' => '', '%username' => ''})
29
29
  end
@@ -0,0 +1,39 @@
1
+ require 'optparse'
2
+ require 'json'
3
+ require 'morpheus/logging'
4
+ require 'morpheus/cli/cli_command'
5
+
6
+ class Morpheus::Cli::GetPromptCommand
7
+ include Morpheus::Cli::CliCommand
8
+ set_command_name :'get-prompt'
9
+ set_command_hidden
10
+
11
+ def handle(args)
12
+ use_echo = false
13
+ options = {}
14
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
15
+ opts.banner = "Usage: morpheus #{command_name}"
16
+ build_common_options(opts, options, [])
17
+ opts.on('-e', '--echo', "Use echo to display the prompt, displaying ansi colors and variables." ) do
18
+ use_echo = true
19
+ end
20
+ opts.footer = <<-EOT
21
+ Display the current morpheus shell prompt value.
22
+ This value can be set using `set-prompt [shell-prompt]`.
23
+ EOT
24
+ end
25
+ optparse.parse!(args)
26
+ if args.count != 0
27
+ print_error Morpheus::Terminal.angry_prompt
28
+ puts_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.inspect}\n#{optparse}"
29
+ return 1
30
+ end
31
+ if use_echo
32
+ my_terminal.execute("echo #{my_terminal.prompt}")
33
+ else
34
+ puts self.my_terminal.prompt
35
+ end
36
+ return 0
37
+ end
38
+
39
+ end
@@ -0,0 +1,76 @@
1
+ require 'optparse'
2
+ require 'json'
3
+ require 'morpheus/logging'
4
+ require 'morpheus/cli/cli_command'
5
+
6
+ class Morpheus::Cli::HistoryCommand
7
+ include Morpheus::Cli::CliCommand
8
+ set_command_name :'history'
9
+ set_command_hidden
10
+
11
+ # todo: support all the other :list options too, not just max
12
+ # AND start logging every terminal command, not just shell...
13
+ def handle(args)
14
+ options = {}
15
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
16
+ opts.banner = "Usage: morpheus #{command_name}"
17
+ # opts.on( '-m', '--max MAX', "Max Results" ) do |max|
18
+ # options[:max] = max.to_i
19
+ # end
20
+ # opts.on( '-o', '--offset OFFSET', "Offset Results" ) do |offset|
21
+ # options[:offset] = offset.to_i.abs
22
+ # end
23
+ # opts.on( '-s', '--search PHRASE', "Search Phrase" ) do |phrase|
24
+ # options[:phrase] = phrase
25
+ # end
26
+ # opts.on( '-S', '--sort ORDER', "Sort Order" ) do |v|
27
+ # options[:sort] = v
28
+ # end
29
+ # opts.on( '-D', '--desc', "Reverse Sort Order" ) do |v|
30
+ # options[:direction] = "desc"
31
+ # end
32
+ opts.on( '-n', '--max-commands MAX', "Max Results. Default is 25" ) do |val|
33
+ options[:max] = val
34
+ end
35
+ opts.add_hidden_option('-n')
36
+ opts.on( nil, '--flush', "Flush history, purges entire shell history file." ) do |val|
37
+ options[:do_flush] = true
38
+ end
39
+ build_common_options(opts, options, [:list, :auto_confirm])
40
+ opts.footer = <<-EOT
41
+ Print command history.
42
+ The --flush option can be used to purge the history.
43
+
44
+ Examples:
45
+ history
46
+ history -m 100
47
+ history --flush
48
+
49
+ EOT
50
+ end
51
+ raw_cmd = "#{command_name} #{args.join(' ')}"
52
+ optparse.parse!(args)
53
+ if args.count != 0
54
+ print_error Morpheus::Terminal.angry_prompt
55
+ puts_error "wrong number of arguments, expected 0 and got (#{args.count}) #{args.join(' ')}\n#{optparse}"
56
+ return 1
57
+ end
58
+ if options[:do_flush]
59
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to flush your command history?")
60
+ return 9, "aborted command"
61
+ end
62
+ Morpheus::Cli::Shell.instance.flush_history
63
+ return 0
64
+ else
65
+ max_commands = options[:max] || 25
66
+ Morpheus::Cli::Shell.instance.print_history(max_commands)
67
+ last_cmd = Morpheus::Cli::Shell.instance.last_command
68
+ # log history, but not consecutive log entries
69
+ if last_cmd.nil? || last_cmd[:command] != raw_cmd
70
+ Morpheus::Cli::Shell.instance.log_history_command(raw_cmd)
71
+ end
72
+ return 0
73
+ end
74
+ end
75
+
76
+ end
@@ -13,7 +13,7 @@ class Morpheus::Cli::LogLevelCommand
13
13
  optparse = Morpheus::Cli::OptionParser.new do|opts|
14
14
  opts.banner = "Usage: morpheus #{command_name} [debug|info|0|1]"
15
15
  #build_common_options(opts, options, [])
16
- opts.on('-h', '--help', "Prints this help" ) do
16
+ opts.on('-h', '--help', "Print this help" ) do
17
17
  puts opts
18
18
  exit
19
19
  end
@@ -41,7 +41,7 @@ class Morpheus::Cli::ManCommand
41
41
  Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
42
42
  ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
43
43
  end
44
- opts.on('-h', '--help', "Prints this help" ) do
44
+ opts.on('-h', '--help', "Print this help" ) do
45
45
  puts opts
46
46
  exit
47
47
  end
@@ -184,7 +184,7 @@ EOT
184
184
  --noprofile Do not read and execute the personal initialization script .morpheus_profile
185
185
  -C, --nocolor Disable ANSI coloring
186
186
  -V, --debug Print extra output for debugging.
187
- -h, --help Prints this help
187
+ -h, --help Print this help
188
188
 
189
189
  ## COMMON OPTIONS
190
190
 
@@ -0,0 +1,14 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ # This is for deleting files and directories!
4
+ class Morpheus::Cli::RemoveFileCommand
5
+ include Morpheus::Cli::CliCommand
6
+ set_command_name :rm
7
+ set_command_hidden
8
+
9
+ def handle(args)
10
+ print_red_alert "#{command_name} is not yet supported"
11
+ return -1
12
+ end
13
+
14
+ end
@@ -0,0 +1,54 @@
1
+ require 'optparse'
2
+ require 'json'
3
+ require 'morpheus/logging'
4
+ require 'morpheus/cli/cli_command'
5
+
6
+ class Morpheus::Cli::SetPromptCommand
7
+ include Morpheus::Cli::CliCommand
8
+ set_command_name :'set-prompt'
9
+ set_command_hidden
10
+
11
+ def handle(args)
12
+ options = {}
13
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
14
+ opts.banner = "Usage: morpheus #{command_name} [prompt]"
15
+ opts.on('-h', '--help', "Print this help" ) do
16
+ puts opts
17
+ exit
18
+ end
19
+ variable_map = Morpheus::Cli::Echo.variable_map
20
+ formatted_variable_map = " " + variable_map.keys.join(' ')
21
+ opts.footer = <<-EOT
22
+ Customize your morpheus shell prompt.
23
+
24
+ [prompt] is required. This is the string the terminal prints when you interact with it.
25
+
26
+ Examples:
27
+ set-prompt "morpheus $ "
28
+ set-prompt "%cyanmorpheus> "
29
+ set-prompt "[%magenta%remote%reset] %cyan%username> "
30
+ set-prompt "%green%username%reset@%remote morph %magenta> %reset"
31
+ set-prompt "%cyan%username%reset@%magenta%remote %cyanmorpheus> %reset"
32
+
33
+ The available variables are:
34
+ #{formatted_variable_map}
35
+
36
+ The default prompt is: "%cyanmorpheus> %reset"
37
+ The value may also be set through the enviroment variable MORPHEUS_PS1.
38
+ EOT
39
+ end
40
+ optparse.parse!(args)
41
+ if args.count != 1
42
+ print_error Morpheus::Terminal.angry_prompt
43
+ puts_error "wrong number of arguments, expected 1 and got (#{args.count}) #{args.inspect}\n#{optparse}"
44
+ return 1
45
+ end
46
+ # do it
47
+ self.my_terminal.prompt = args[0]
48
+ # Morpheus::Terminal.instance.prompt = args[0]
49
+ Morpheus::Cli::Shell.instance.recalculate_prompt()
50
+ Morpheus::Cli::Echo.recalculate_variable_map()
51
+ return 0
52
+ end
53
+
54
+ end
@@ -22,7 +22,7 @@ EOT
22
22
  optparse = Morpheus::Cli::OptionParser.new do|opts|
23
23
  opts.banner = usage
24
24
  #build_common_options(opts, options, [])
25
- opts.on('-h', '--help', "Prints this help" ) do
25
+ opts.on('-h', '--help', "Print this help" ) do
26
26
  puts opts
27
27
  exit
28
28
  end
@@ -0,0 +1,14 @@
1
+ require 'morpheus/cli/cli_command'
2
+
3
+ # This is for writing STDIN to files(s)
4
+ class Morpheus::Cli::TeeCommand
5
+ include Morpheus::Cli::CliCommand
6
+ set_command_name :tee
7
+ set_command_hidden
8
+
9
+ def handle(args)
10
+ print_red_alert "#{command_name} is not yet supported"
11
+ return -1
12
+ end
13
+
14
+ end
@@ -18,112 +18,183 @@ module Morpheus
18
18
  @appliance_url = appliance_url
19
19
  end
20
20
 
21
- def request_credentials(opts = {})
22
- #puts "request_credentials(#{opts})"
21
+ # request_credentials will fetch a credentials wallet (access_token, refresh_token, etc)
22
+ # By default this uses the saved credentials for the current appliance.
23
+ # If not logged in, it will prompt for username and password to
24
+ # authenticate with the /oauth/token API to receive an access_token.
25
+ # If :username and :password are passed, then
26
+ # Pass :remote_token to skip prompting and the auth api request.
27
+ # @param options - Hash of optional settings.
28
+ # :username - Username for prompt.
29
+ # :password - Password for prompt.
30
+ # :remote_url - Use this url instead of the one from the current appliance. Credentials will not be saved.
31
+ # :remote_token - Use this access_token, skip prompting and API request.
32
+ # :remote_username - Username for authentication with --remote, skips saving credentials
33
+ # :remote_password - Password for authentication with --remote, skips saving credentials
34
+ # :test_only - Test only. Saved credentials will not be updated.
35
+ # @return Hash wallet like {"access_token":"ec68be138765...", "refresh_token":"ec68be138765..."}
36
+ # or nil if unable to find credentials.
37
+ def request_credentials(options = {}, do_save=true)
38
+ #puts "request_credentials(#{options})"
23
39
  username = nil
24
40
  password = nil
25
- access_token = nil
26
- skip_save = false
41
+ wallet = nil
42
+
27
43
 
28
- if opts[:remote_token]
44
+
45
+ if options[:remote_token]
46
+ # user passed in a token to login with.
47
+ # this should get token info from /oauth/token
48
+ # OR whoami should return other wallet info like access token or maybe just the expiration date
49
+ # for now, it just stores the access token without other wallet info
29
50
  begin
30
- whoami_interface = Morpheus::WhoamiInterface.new(opts[:remote_token], nil, nil, @appliance_url)
51
+ whoami_interface = Morpheus::WhoamiInterface.new(options[:remote_token], nil, nil, @appliance_url)
52
+ if options[:dry_run]
53
+ print_dry_run whoami_interface.dry.get()
54
+ return nil
55
+ end
31
56
  whoami_response = whoami_interface.get()
32
- if opts[:json]
57
+ if options[:json]
33
58
  print JSON.pretty_generate(whoami_response)
34
59
  print reset, "\n"
35
60
  end
36
- access_token = opts[:remote_token]
61
+ # store mock /oauth/token auth_interface.login() result
62
+ json_response = {'access_token' => options[:remote_token], 'token_type' => 'bearer'}
37
63
  username = whoami_response['user']['username']
38
- unless skip_save
39
- save_credentials(@appliance_name, access_token)
64
+ login_date = Time.now
65
+ expire_date = nil
66
+ if json_response['expires_in']
67
+ expire_date = login_date.to_i + json_response['expires_in'].to_i
40
68
  end
69
+ wallet = {
70
+ 'username' => username,
71
+ 'login_date' => login_date.to_i,
72
+ 'expire_date' => expire_date ? expire_date.to_i : nil,
73
+ 'access_token' => json_response['access_token'],
74
+ 'refresh_token' => json_response['refresh_token'],
75
+ 'token_type' => json_response['token_type']
76
+ }
41
77
  rescue ::RestClient::Exception => e
42
78
  #raise e
43
79
  print_red_alert "Token not valid."
44
- if opts[:debug] || opts[:debug]
45
- print_rest_exception(e, opts)
80
+ if options[:debug] || options[:debug]
81
+ print_rest_exception(e, options)
46
82
  end
47
- access_token = nil
83
+ wallet = nil
48
84
  end
49
85
  else
50
-
51
- if !opts[:remote_username].nil?
52
- username = opts[:remote_username]
53
- password = opts[:remote_password]
54
- skip_save = opts[:remote_url] ? true : false
86
+
87
+ # ok prompt for creds..
88
+ username = options['username'] || options[:username] || nil
89
+ password = options['password'] || options[:password] || nil
90
+
91
+ if options[:remote_username]
92
+ username = options[:remote_username]
93
+ password = options[:remote_password]
94
+ if do_save == true
95
+ do_save = (options[:remote_url] ? false : true)
96
+ end
55
97
  else
56
- access_token = load_saved_credentials
98
+ # maybe just if check if options[:test_only] != true
99
+ # if do_save == true
100
+ # wallet = load_saved_credentials
101
+ # end
57
102
  end
58
- if access_token
59
- return access_token
60
- end
61
- unless opts[:quiet] || opts[:no_prompt]
62
- # if username.empty? || password.empty?
63
- print "Enter Morpheus Credentials for #{display_appliance(@appliance_name, @appliance_url)}\n",reset
64
- # end
65
- if username.empty?
66
- print "Username: #{required_blue_prompt} "
67
- username = $stdin.gets.chomp!
68
- else
69
- print "Username: #{required_blue_prompt} #{username}\n"
70
- end
71
- if password.empty?
72
- print "Password: #{required_blue_prompt} "
73
- password = STDIN.noecho(&:gets).chomp!
74
- print "\n"
75
- else
76
- print "Password: #{required_blue_prompt} \n"
103
+
104
+ if wallet.nil?
105
+ unless options[:quiet] || options[:no_prompt]
106
+ # if username.empty? || password.empty?
107
+ if options[:test_only]
108
+ print "Test Morpheus Credentials for #{display_appliance(@appliance_name, @appliance_url)}\n",reset
109
+ else
110
+ print "Enter Morpheus Credentials for #{display_appliance(@appliance_name, @appliance_url)}\n",reset
111
+ end
112
+ # end
113
+ if username.empty?
114
+ print "Username: #{required_blue_prompt} "
115
+ username = $stdin.gets.chomp!
116
+ else
117
+ print "Username: #{required_blue_prompt} #{username}\n"
118
+ end
119
+ if password.empty?
120
+ print "Password: #{required_blue_prompt} "
121
+ # wtf is this STDIN and $stdin and not my_terminal.stdin ?
122
+ password = STDIN.noecho(&:gets).chomp!
123
+ print "\n"
124
+ else
125
+ print "Password: #{required_blue_prompt} \n"
126
+ end
77
127
  end
78
- end
79
- if username.empty? || password.empty?
80
- print_red_alert "Username and password are required to login."
81
- return nil
82
- end
83
- begin
84
- auth_interface = Morpheus::AuthInterface.new(@appliance_url)
85
- json_response = auth_interface.login(username, password)
86
- if opts[:json]
87
- print JSON.pretty_generate(json_response)
88
- print reset, "\n"
128
+ if username.empty? || password.empty?
129
+ print_red_alert "Username and password are required to login."
130
+ return nil
89
131
  end
90
- access_token = json_response['access_token']
91
- if access_token && access_token != ""
92
- unless skip_save
93
- save_credentials(@appliance_name, access_token)
132
+ begin
133
+ auth_interface = Morpheus::AuthInterface.new(@appliance_url)
134
+ auth_interface.setopts(options)
135
+ if options[:dry_run]
136
+ print_dry_run auth_interface.dry.login(username, password)
137
+ return nil
94
138
  end
95
- # return access_token
96
- else
97
- print_red_alert "Credentials not verified."
98
- # return nil
99
- end
100
- rescue ::RestClient::Exception => e
101
- #raise e
102
- if (e.response && e.response.code == 400)
103
- json_response = JSON.parse(e.response.to_s)
104
- error_msg = json_response['error_description'] || "Credentials not verified."
105
- print_red_alert error_msg
106
- if opts[:json]
107
- json_response = JSON.parse(e.response.to_s)
139
+ json_response = auth_interface.login(username, password)
140
+ if options[:json]
108
141
  print JSON.pretty_generate(json_response)
109
142
  print reset, "\n"
110
143
  end
111
- else
112
- print_rest_exception(e, opts)
144
+ #wallet = json_response
145
+ login_date = Time.now
146
+ expire_date = nil
147
+ if json_response['expires_in']
148
+ expire_date = login_date.to_i + json_response['expires_in'].to_i
149
+ end
150
+ wallet = {
151
+ 'username' => username,
152
+ 'login_date' => login_date.to_i,
153
+ 'expire_date' => expire_date ? expire_date.to_i : nil,
154
+ 'access_token' => json_response['access_token'],
155
+ 'refresh_token' => json_response['refresh_token'],
156
+ 'token_type' => json_response['token_type']
157
+ }
158
+
159
+ rescue ::RestClient::Exception => e
160
+ #raise e
161
+ if (e.response && e.response.code == 400)
162
+ json_response = JSON.parse(e.response.to_s)
163
+ error_msg = json_response['error_description'] || "Credentials not verified."
164
+ print_red_alert error_msg
165
+ if options[:json]
166
+ json_response = JSON.parse(e.response.to_s)
167
+ print JSON.pretty_generate(json_response)
168
+ print reset, "\n"
169
+ end
170
+ else
171
+ print_rest_exception(e, options)
172
+ end
173
+ wallet = nil
113
174
  end
114
- access_token = nil
115
- end
116
175
 
176
+ end
117
177
  end
118
178
 
179
+ if do_save && @appliance_name
180
+
119
181
 
120
- unless skip_save
121
182
  begin
122
- # save pertinent session info to the appliance
183
+ # save pertinent session info to the appliance
184
+ save_credentials(@appliance_name, wallet)
123
185
  now = Time.now.to_i
124
186
  appliance = ::Morpheus::Cli::Remote.load_remote(@appliance_name)
187
+
188
+ if wallet && wallet['access_token']
189
+ save_credentials(@appliance_name, wallet)
190
+ else
191
+ clear_saved_credentials(@appliance_name)
192
+ end
125
193
  if appliance
126
- if access_token
194
+ if wallet && wallet['access_token']
195
+ # save wallet to credentials file
196
+ save_credentials(@appliance_name, wallet)
197
+ # save appliances file
127
198
  appliance = ::Morpheus::Cli::Remote.load_remote(@appliance_name)
128
199
  appliance[:authenticated] = true
129
200
  appliance[:username] = username
@@ -132,26 +203,37 @@ module Morpheus
132
203
  appliance[:last_success_at] = now
133
204
  ::Morpheus::Cli::Remote.save_remote(@appliance_name, appliance)
134
205
  else
206
+ # could be nice and not do this
207
+ #logout()
208
+ #save wallet to credentials file
209
+ clear_saved_credentials(@appliance_name)
135
210
  now = Time.now.to_i
136
211
  appliance = ::Morpheus::Cli::Remote.load_remote(@appliance_name)
137
212
  appliance[:authenticated] = false
138
- #appliance[:username] = username
213
+ old_username = appliance.delete(:username)
214
+ appliance[:last_logout_at] = Time.now.to_i
139
215
  #appliance[:last_login_at] = now
140
216
  #appliance[:error] = "Credentials not verified"
217
+ appliance.delete(:username)
141
218
  ::Morpheus::Cli::Remote.save_remote(@appliance_name, appliance)
219
+ if old_username
220
+ print reset,"You have been automatically logged out. Goodbye #{old_username}!", reset, "\n"
221
+ end
142
222
  end
223
+
143
224
  end
144
225
  rescue => e
145
- #puts "failed to update remote appliance config: (#{e.class}) #{e.message}"
226
+ Morpheus::Logging::DarkPrinter.puts "failed to update remote appliance config: (#{e.class}) #{e.message}"
227
+ ensure
228
+ #::Morpheus::Cli::Remote.recalculate_variable_map()
146
229
  end
147
230
  end
148
-
149
- return access_token
231
+
232
+ return wallet
150
233
  end
151
234
 
152
- def login(opts = {})
153
- clear_saved_credentials(@appliance_name)
154
- request_credentials(opts)
235
+ def login(options = {}, do_save=true)
236
+ request_credentials(options, do_save)
155
237
  end
156
238
 
157
239
  def logout()
@@ -164,21 +246,123 @@ module Morpheus
164
246
  appliance[:last_logout_at] = Time.now.to_i
165
247
  ::Morpheus::Cli::Remote.save_remote(@appliance_name, appliance)
166
248
  end
249
+ ::Morpheus::Cli::Remote.recalculate_variable_map()
167
250
  true
168
251
  end
169
252
 
253
+ def use_refresh_token(options = {})
254
+ #puts "use_refresh_token(#{options})"
255
+
256
+ wallet = load_saved_credentials
257
+
258
+ if wallet.nil?
259
+ print_red_alert yellow,"You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}",reset,"\n"
260
+ return nil
261
+ end
262
+
263
+ if wallet['refresh_token'].nil?
264
+ print_red_alert yellow,"No refresh token found for #{display_appliance(@appliance_name, @appliance_url)}",reset,"\n"
265
+ return nil
266
+ end
267
+
268
+
269
+ username = wallet['username']
270
+
271
+ begin
272
+ auth_interface.setopts(options)
273
+ auth_interface = Morpheus::AuthInterface.new(@appliance_url)
274
+ if options[:dry_run]
275
+ print_dry_run auth_interface.dry.use_refresh_token(wallet['refresh_token'])
276
+ return nil
277
+ end
278
+ json_response = auth_interface.use_refresh_token(wallet['refresh_token'])
279
+ #wallet = json_response
280
+ login_date = Time.now
281
+ expire_date = nil
282
+ if json_response['expires_in']
283
+ expire_date = login_date.to_i + json_response['expires_in'].to_i
284
+ end
285
+ wallet = {
286
+ 'username' => username,
287
+ 'login_date' => login_date.to_i,
288
+ 'expire_date' => expire_date ? expire_date.to_i : nil,
289
+ 'access_token' => json_response['access_token'],
290
+ 'refresh_token' => json_response['refresh_token'],
291
+ 'token_type' => json_response['token_type']
292
+ }
293
+
294
+ rescue ::RestClient::Exception => e
295
+ #raise e
296
+ if (e.response && e.response.code == 400)
297
+ json_response = JSON.parse(e.response.to_s)
298
+ error_msg = json_response['error_description'] || "Refresh token not valid."
299
+ print_red_alert error_msg
300
+ if options[:json]
301
+ json_response = JSON.parse(e.response.to_s)
302
+ print JSON.pretty_generate(json_response)
303
+ print reset, "\n"
304
+ end
305
+ else
306
+ print_rest_exception(e, options)
307
+ end
308
+ wallet = nil
309
+ end
310
+
311
+ # save wallet to credentials file
312
+ save_credentials(@appliance_name, wallet)
313
+
314
+ begin
315
+ # save pertinent session info to the appliance
316
+ now = Time.now.to_i
317
+ appliance = ::Morpheus::Cli::Remote.load_remote(@appliance_name)
318
+ if appliance
319
+ if wallet && wallet['access_token']
320
+ appliance = ::Morpheus::Cli::Remote.load_remote(@appliance_name)
321
+ appliance[:authenticated] = true
322
+ appliance[:username] = username
323
+ appliance[:status] = "ready"
324
+ appliance[:last_login_at] = now
325
+ appliance[:last_success_at] = now
326
+ ::Morpheus::Cli::Remote.save_remote(@appliance_name, appliance)
327
+ else
328
+ now = Time.now.to_i
329
+ appliance = ::Morpheus::Cli::Remote.load_remote(@appliance_name)
330
+ appliance[:authenticated] = false
331
+ #appliance[:username] = username
332
+ #appliance[:last_login_at] = now
333
+ #appliance[:error] = "Credentials not verified"
334
+ ::Morpheus::Cli::Remote.save_remote(@appliance_name, appliance)
335
+ end
336
+ end
337
+ rescue => e
338
+ Morpheus::Logging::DarkPrinter.puts "failed to update remote appliance config: (#{e.class}) #{e.message}"
339
+ end
340
+
341
+
342
+ return wallet
343
+ end
344
+
170
345
  def clear_saved_credentials(appliance_name)
171
346
  @@appliance_credentials_map = load_credentials_file || {}
172
- @@appliance_credentials_map.delete(appliance_name)
347
+ @@appliance_credentials_map.delete(appliance_name.to_s)
348
+ @@appliance_credentials_map.delete(appliance_name.to_sym)
173
349
  Morpheus::Logging::DarkPrinter.puts "clearing credentials for #{appliance_name} from file #{credentials_file_path}" if Morpheus::Logging.debug?
174
350
  File.open(credentials_file_path, 'w') {|f| f.write @@appliance_credentials_map.to_yaml } #Store
351
+ ::Morpheus::Cli::Remote.recalculate_variable_map()
352
+ true
175
353
  end
176
354
 
177
355
  def load_saved_credentials(reload=false)
178
356
  if reload || !defined?(@@appliance_credentials_map) || @@appliance_credentials_map.nil?
179
357
  @@appliance_credentials_map = load_credentials_file || {}
180
358
  end
181
- return @@appliance_credentials_map[@appliance_name]
359
+ # ok, we switched symbols to strings, because symbols suck in yaml! need to support both
360
+ # also we switched from just a token (symbol) to a whole object of strings
361
+ wallet = @@appliance_credentials_map[@appliance_name.to_s] || @@appliance_credentials_map[@appliance_name.to_sym]
362
+ if wallet.is_a?(String)
363
+ wallet = {'access_token' => wallet}
364
+ end
365
+ return wallet
182
366
  end
183
367
 
184
368
  def load_credentials_file
@@ -195,14 +379,19 @@ module Morpheus
195
379
  File.join(Morpheus::Cli.home_directory, "credentials")
196
380
  end
197
381
 
198
- def save_credentials(appliance_name, token)
199
- # credential_map = appliance_credentials_map
382
+ # credentials wallet is {'access_token': '...', 'refresh_token': '...' 'expiration': '2019-01-01...'}
383
+ def save_credentials(appliance_name, wallet)
200
384
  # reloading file is better for now, otherwise you can lose credentials with multiple shells.
201
385
  credential_map = load_credentials_file || {}
202
- if credential_map.nil?
203
- credential_map = {}
386
+
387
+ if wallet
388
+ credential_map[appliance_name.to_s] = wallet
389
+ else
390
+ # nil mean remove the damn thing
391
+ credential_map.delete(appliance_name.to_s)
204
392
  end
205
- credential_map[appliance_name] = token
393
+ # always remove symbol, which was used pre 3.6.9
394
+ credential_map.delete(appliance_name.to_sym)
206
395
  begin
207
396
  fn = credentials_file_path
208
397
  if !Dir.exists?(File.dirname(fn))