morpheus-cli 2.10.3 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/bin/morpheus +5 -96
  3. data/lib/morpheus/api/api_client.rb +23 -1
  4. data/lib/morpheus/api/checks_interface.rb +106 -0
  5. data/lib/morpheus/api/incidents_interface.rb +102 -0
  6. data/lib/morpheus/api/monitoring_apps_interface.rb +47 -0
  7. data/lib/morpheus/api/monitoring_contacts_interface.rb +47 -0
  8. data/lib/morpheus/api/monitoring_groups_interface.rb +47 -0
  9. data/lib/morpheus/api/monitoring_interface.rb +36 -0
  10. data/lib/morpheus/api/option_type_lists_interface.rb +47 -0
  11. data/lib/morpheus/api/option_types_interface.rb +47 -0
  12. data/lib/morpheus/api/roles_interface.rb +0 -1
  13. data/lib/morpheus/api/setup_interface.rb +19 -9
  14. data/lib/morpheus/cli.rb +20 -1
  15. data/lib/morpheus/cli/accounts.rb +8 -3
  16. data/lib/morpheus/cli/app_templates.rb +19 -11
  17. data/lib/morpheus/cli/apps.rb +52 -37
  18. data/lib/morpheus/cli/cli_command.rb +229 -53
  19. data/lib/morpheus/cli/cli_registry.rb +48 -40
  20. data/lib/morpheus/cli/clouds.rb +55 -26
  21. data/lib/morpheus/cli/command_error.rb +12 -0
  22. data/lib/morpheus/cli/credentials.rb +68 -26
  23. data/lib/morpheus/cli/curl_command.rb +98 -0
  24. data/lib/morpheus/cli/dashboard_command.rb +2 -7
  25. data/lib/morpheus/cli/deployments.rb +4 -4
  26. data/lib/morpheus/cli/deploys.rb +1 -2
  27. data/lib/morpheus/cli/dot_file.rb +5 -8
  28. data/lib/morpheus/cli/error_handler.rb +179 -15
  29. data/lib/morpheus/cli/groups.rb +21 -13
  30. data/lib/morpheus/cli/hosts.rb +220 -110
  31. data/lib/morpheus/cli/instance_types.rb +2 -2
  32. data/lib/morpheus/cli/instances.rb +257 -167
  33. data/lib/morpheus/cli/key_pairs.rb +15 -9
  34. data/lib/morpheus/cli/library.rb +673 -27
  35. data/lib/morpheus/cli/license.rb +2 -2
  36. data/lib/morpheus/cli/load_balancers.rb +4 -4
  37. data/lib/morpheus/cli/log_level_command.rb +6 -4
  38. data/lib/morpheus/cli/login.rb +17 -3
  39. data/lib/morpheus/cli/logout.rb +25 -11
  40. data/lib/morpheus/cli/man_command.rb +388 -0
  41. data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -1
  42. data/lib/morpheus/cli/mixins/monitoring_helper.rb +434 -0
  43. data/lib/morpheus/cli/mixins/print_helper.rb +620 -112
  44. data/lib/morpheus/cli/mixins/provisioning_helper.rb +1 -1
  45. data/lib/morpheus/cli/monitoring_apps_command.rb +29 -0
  46. data/lib/morpheus/cli/monitoring_checks_command.rb +427 -0
  47. data/lib/morpheus/cli/monitoring_contacts_command.rb +373 -0
  48. data/lib/morpheus/cli/monitoring_groups_command.rb +29 -0
  49. data/lib/morpheus/cli/monitoring_incidents_command.rb +711 -0
  50. data/lib/morpheus/cli/option_types.rb +10 -1
  51. data/lib/morpheus/cli/recent_activity_command.rb +2 -5
  52. data/lib/morpheus/cli/remote.rb +874 -134
  53. data/lib/morpheus/cli/roles.rb +54 -27
  54. data/lib/morpheus/cli/security_group_rules.rb +2 -2
  55. data/lib/morpheus/cli/security_groups.rb +23 -19
  56. data/lib/morpheus/cli/set_prompt_command.rb +50 -0
  57. data/lib/morpheus/cli/shell.rb +222 -157
  58. data/lib/morpheus/cli/tasks.rb +19 -15
  59. data/lib/morpheus/cli/users.rb +27 -17
  60. data/lib/morpheus/cli/version.rb +1 -1
  61. data/lib/morpheus/cli/virtual_images.rb +28 -13
  62. data/lib/morpheus/cli/whoami.rb +131 -52
  63. data/lib/morpheus/cli/workflows.rb +24 -9
  64. data/lib/morpheus/formatters.rb +195 -3
  65. data/lib/morpheus/logging.rb +86 -0
  66. data/lib/morpheus/terminal.rb +371 -0
  67. data/scripts/generate_morpheus_commands_help.morpheus +60 -0
  68. metadata +21 -2
@@ -45,7 +45,7 @@ class Morpheus::Cli::License
45
45
  puts "No License Currently Applied to the appliance."
46
46
  exit 1
47
47
  else
48
- print "\n", cyan, "License\n=======\n"
48
+ print_h1 "License"
49
49
  max_memory = Filesize.from("#{license['license']['maxMemory']} B").pretty
50
50
  max_storage = Filesize.from("#{license['license']['maxStorage']} B").pretty
51
51
  used_memory = Filesize.from("#{license['usedMemory']} B").pretty
@@ -77,7 +77,7 @@ class Morpheus::Cli::License
77
77
  key = args[0]
78
78
  else
79
79
  v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'licenseKey', 'fieldLabel' => 'License Key', 'type' => 'text', 'required' => true}], options[:options])
80
- instance_name = v_prompt['licenseKey'] || ''
80
+ key = v_prompt['licenseKey'] || ''
81
81
  end
82
82
  if options[:dry_run]
83
83
  print_dry_run @license_interface.dry.apply(key)
@@ -47,9 +47,9 @@ class Morpheus::Cli::LoadBalancers
47
47
  print JSON.pretty_generate(json_response)
48
48
  else
49
49
  lbs = json_response['loadBalancers']
50
- print "\n" ,cyan, bold, "Morpheus Load Balancers\n","==================", reset, "\n\n"
50
+ print_h1 "Morpheus Load Balancers"
51
51
  if lbs.empty?
52
- puts yellow,"No load balancers currently configured.",reset
52
+ print cyan,"No load balancers found.",reset,"\n"
53
53
  else
54
54
  print cyan
55
55
  lb_table_data = lbs.collect do |lb|
@@ -186,9 +186,9 @@ class Morpheus::Cli::LoadBalancers
186
186
  print JSON.pretty_generate(json_response)
187
187
  else
188
188
  lb_types = json_response['loadBalancerTypes']
189
- print "\n" ,cyan, bold, "Morpheus Load Balancer Types\n","============================", reset, "\n\n"
189
+ print_h1 "Morpheus Load Balancer Types"
190
190
  if lb_types.nil? || lb_types.empty?
191
- puts yellow,"No lb types currently exist on this appliance. This could be a seed issue.",reset
191
+ print yellow,"No lb types currently exist on this appliance. This could be a seed issue.",reset,"\n"
192
192
  else
193
193
  print cyan
194
194
  lb_table_data = lb_types.collect do |lb_type|
@@ -1,6 +1,7 @@
1
1
  require 'optparse'
2
- require 'morpheus/cli/cli_command'
3
2
  require 'json'
3
+ require 'morpheus/logging'
4
+ require 'morpheus/cli/cli_command'
4
5
 
5
6
  class Morpheus::Cli::LogLevelCommand
6
7
  include Morpheus::Cli::CliCommand
@@ -34,13 +35,14 @@ EOT
34
35
  end
35
36
  if ["debug", "0"].include?(args[0].to_s.strip.downcase)
36
37
  Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
37
- ::RestClient.log = Morpheus::Logging.debug? ? STDOUT : nil
38
+ ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
39
+ Morpheus::Logging::DarkPrinter.puts "debug enabled"
38
40
  elsif ["info", "1"].include?(args[0].to_s.strip.downcase)
39
41
  Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::INFO)
40
- ::RestClient.log = Morpheus::Logging.debug? ? STDOUT : nil
42
+ ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
41
43
  elsif args[0].to_i < 6
42
44
  Morpheus::Logging.set_log_level(args[0].to_i)
43
- ::RestClient.log = Morpheus::Logging.debug? ? STDOUT : nil
45
+ ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
44
46
  else
45
47
  puts optparse
46
48
  return false
@@ -49,7 +49,7 @@ class Morpheus::Cli::Login
49
49
  @appliance_name, @appliance_url = nil, nil
50
50
  end
51
51
  if !@appliance_name
52
- print_red_alert "You have no appliance named '#{options[:remote]}' configured. See the `remote add` command."
52
+ print_red_alert "You have no appliance named '#{options[:remote]}' configured. See the `remote list` command."
53
53
  return false
54
54
  end
55
55
  else
@@ -70,11 +70,25 @@ class Morpheus::Cli::Login
70
70
  options[:remote_username] = username if username
71
71
  options[:remote_password] = password if password
72
72
  #options[:remote_url] = true # will skip credentials save
73
- Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).login(options)
73
+ login_result = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).login(options)
74
+
75
+ # check to see if we got credentials, or just look at login_result above...
76
+ creds = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials() # .load_saved_credentials(true)
77
+
78
+ # recalculate shell prompt after this change
79
+ if Morpheus::Cli::Shell.instance
80
+ Morpheus::Cli::Shell.instance.reinitialize()
81
+ end
82
+
83
+ if creds
84
+ return 0 # , nil
85
+ else
86
+ return 1 # , "Login failed"
87
+ end
74
88
 
75
89
  rescue RestClient::Exception => e
76
90
  print_rest_exception(e, options)
77
- exit 1
91
+ return 1
78
92
  end
79
93
 
80
94
  end
@@ -32,28 +32,42 @@ class Morpheus::Cli::Logout
32
32
  options = {}
33
33
  optparse = OptionParser.new do|opts|
34
34
  opts.banner = usage
35
- build_common_options(opts, options, [:remote]) # todo: support :remote too perhaps
35
+ build_common_options(opts, options, [:remote, :quiet])
36
36
  end
37
37
  optparse.parse!(args)
38
- connect(options)
38
+ # connect(options)
39
+ # establish @appliance_name, @appliance_url,
40
+ @api_client = establish_remote_appliance_connection(options.merge({:no_prompt => true, :skip_verify_access_token => true}))
39
41
 
40
42
  begin
41
43
  if !@appliance_name
42
- print yellow,"Please specify a Morpheus Appliance to logout of with -r or see the command `remote use`#{reset}\n"
43
- return
44
+ print_error Morpheus::Terminal.angry_prompt
45
+ puts_error "Please specify a Morpheus Appliance to logout of with -r or see the command `remote use`"
46
+ return 1
44
47
  end
45
- creds = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials()
46
- if !creds
47
- print yellow,"You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}\n",reset
48
- return 0
48
+ creds = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url)
49
+ token = creds.saved_credentials
50
+ if !token
51
+ if !options[:quiet]
52
+ puts "You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}"
53
+ end
49
54
  else
55
+ # todo: need to tell the server to delete the token too..
56
+ # delete token from credentials file
57
+ # note: this also handles updating appliance session info
50
58
  Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).logout()
51
- print cyan,"Goodbye\n",reset
59
+ if !options[:quiet]
60
+ puts "#{cyan}Logged out of #{@appliance_name}. Goodbye.#{reset}"
61
+ end
52
62
  end
53
-
63
+ # recalculate shell prompt after this change
64
+ if Morpheus::Cli::Shell.instance
65
+ Morpheus::Cli::Shell.instance.reinitialize()
66
+ end
67
+ return 0
54
68
  rescue RestClient::Exception => e
55
69
  print_rest_exception(e, options)
56
- return 1
70
+ return false
57
71
  end
58
72
 
59
73
  end
@@ -0,0 +1,388 @@
1
+ require 'optparse'
2
+ require 'morpheus/logging'
3
+ require 'morpheus/cli/cli_command'
4
+
5
+ class Morpheus::Cli::ManCommand
6
+ include Morpheus::Cli::CliCommand
7
+ set_command_name :man
8
+ set_command_hidden
9
+
10
+ # this should be read only anyway...
11
+ @@default_editor = "less" # ENV['EDITOR']
12
+
13
+ def handle(args)
14
+ options = {}
15
+ regenerate = false
16
+ editor = @@default_editor
17
+ open_as_link = false # true please
18
+ goto_wiki = false
19
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
20
+ opts.banner = "Usage: morpheus man"
21
+ opts.on('-w','--wiki', "Open the morpheus-cli wiki instead of the local man page") do
22
+ goto_wiki = true
23
+ end
24
+ opts.on('-e','--editor EDITOR', "Specify which program to open the manual with. Default is '#{editor}'.") do |val|
25
+ editor = val
26
+ open_as_link = false
27
+ end
28
+ opts.on('-g','--generate', "Regenerate the manual file") do
29
+ regenerate = true
30
+ end
31
+ opts.on('-q','--quiet', "Do not open manual, for use with the -g option.") do
32
+ options[:quiet] = true
33
+ end
34
+ #build_common_options(opts, options, [:quiet])
35
+ # disable ANSI coloring
36
+ opts.on('-C','--nocolor', "Disable ANSI coloring") do
37
+ Term::ANSIColor::coloring = false
38
+ end
39
+
40
+ opts.on('-V','--debug', "Print extra output for debugging. ") do
41
+ Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG)
42
+ ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil
43
+ end
44
+ opts.on('-h', '--help', "Prints this help" ) do
45
+ puts opts
46
+ exit
47
+ end
48
+ opts.footer = <<-EOT
49
+ Open the morpheus manual located at #{Morpheus::Cli::ManCommand.man_file_path}
50
+ The -g switch be used to regenerate the file.
51
+ EOT
52
+ end
53
+ optparse.parse!(args)
54
+
55
+ if goto_wiki
56
+ link = "https://github.com/gomorpheus/morpheus-cli/wiki/CLI-Manual"
57
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
58
+ system "start #{link}"
59
+ elsif RbConfig::CONFIG['host_os'] =~ /darwin/
60
+ system "open #{link}"
61
+ elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
62
+ system "xdg-open #{link}"
63
+ end
64
+ return 0, nil
65
+ end
66
+
67
+ fn = Morpheus::Cli::ManCommand.man_file_path
68
+ if regenerate || !File.exists?(fn)
69
+ #Morpheus::Logging::DarkPrinter.puts "generating manual #{fn} ..." if Morpheus::Logging.debug?
70
+ Morpheus::Cli::ManCommand.generate_manual()
71
+ end
72
+
73
+ if options[:quiet]
74
+ return 0, nil
75
+ end
76
+
77
+ Morpheus::Logging::DarkPrinter.puts "opening manual file #{fn}" if Morpheus::Logging.debug?
78
+
79
+
80
+ if open_as_link # not used atm
81
+ link = "file://#{fn}"
82
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
83
+ system "start #{link}"
84
+ elsif RbConfig::CONFIG['host_os'] =~ /darwin/
85
+ system "open #{link}"
86
+ elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
87
+ system "xdg-open #{link}"
88
+ end
89
+ return 0, nil
90
+ else
91
+ if editor
92
+ if !system_command_available?(editor)
93
+ raise_command_error "The editor program '#{editor}' is not available on your system."
94
+ # puts_error "#{red}The editor program '#{editor}' is not available on your system.#{reset}"
95
+ # return 1
96
+ end
97
+ system("#{editor} #{fn}")
98
+ else
99
+ raise_command_error "Tell me how to open the manual file #{fn}. Try -e emacs or run export EDITOR=emacs"
100
+ return 1
101
+ end
102
+ end
103
+
104
+ return 0, nil
105
+ end
106
+
107
+ # determine if system command is available
108
+ # uses *nix's `which` command.
109
+ # Prevents using dangerous commands rm,mv,passwd
110
+ # todo: support for Windows and PowerShell
111
+ def system_command_available?(cmd)
112
+ has_it = false
113
+ begin
114
+ cmd = cmd.strip
115
+ if cmd.include?(';') ||
116
+ cmd =~ /^rm/ || cmd.strip =~ /^mv/ || cmd.strip =~ /^passwd/ ||
117
+ cmd.include?("/rm") || cmd.include?("/mv") || cmd.include?("/passwd")
118
+ raise_command_error "The specified system command '#{cmd}' is invalid."
119
+ end
120
+ system("which #{cmd} > /dev/null 2>&1")
121
+ has_it = $?.success?
122
+ rescue => e
123
+ raise e
124
+ end
125
+ return has_it
126
+ end
127
+
128
+ def self.man_file_path
129
+ File.join(Morpheus::Cli.home_directory, "CLI-Manual-#{Morpheus::Cli::VERSION}.md")
130
+ end
131
+
132
+ # def self.save_manual(fn, content)
133
+ # # fn = man_file_path()
134
+ # if !Dir.exists?(File.dirname(fn))
135
+ # FileUtils.mkdir_p(File.dirname(fn))
136
+ # end
137
+ # Morpheus::Logging::DarkPrinter.puts "saving manual to #{fn}" if Morpheus::Logging.debug?
138
+ # File.open(fn, 'w') {|f| f.write content.to_s } #Store
139
+ # FileUtils.chmod(0600, fn)
140
+ # end
141
+
142
+ def self.generate_manual()
143
+ # todo: use pandoc or something else to convert the CLI-Manual.md to a man page
144
+ # and install it, so the os command `man morpheus` will work too.
145
+ fn = man_file_path()
146
+ if !Dir.exists?(File.dirname(fn))
147
+ FileUtils.mkdir_p(File.dirname(fn))
148
+ end
149
+ Morpheus::Logging::DarkPrinter.puts "generating manual #{fn}" if Morpheus::Logging.debug?
150
+
151
+ File.open(fn, 'w') {|f| f.write("") } # clear file
152
+ FileUtils.chmod(0600, fn)
153
+
154
+ manpage = File.new(fn, 'w')
155
+ previous_stdout = $stdout
156
+ $stdout = manpage
157
+ begin
158
+
159
+ $stdout.print <<-ENDTEXT
160
+ ## NAME
161
+
162
+ morpheus - the command line interface for interacting with the Morpheus Data appliance
163
+
164
+ ## SYNOPSIS
165
+
166
+ morpheus [command] [<args>]
167
+
168
+ ## DESCRIPTION
169
+
170
+ Morpheus CLI
171
+
172
+ This is a command line interface for managing a Morpheus Appliance.
173
+ All communication with the remote appliance is done via the Morpheus API.
174
+
175
+ To setup a new appliance, see the `remote add` and `remote setup` commands.
176
+
177
+ To get started, visit https://github.com/gomorpheus/morpheus-cli/wiki/Getting-Started
178
+
179
+ To learn more about the Morpheus Appliance, visit https://www.morpheusdata.com/features
180
+
181
+ To learn more about the Morpheus API, visit http://bertramdev.github.io/morpheus-apidoc/
182
+
183
+ ## GLOBAL OPTIONS
184
+
185
+ Morpheus supports a few global options.
186
+
187
+ -v, --version Print the version.
188
+ --noprofile Do not read and execute the personal initialization script .morpheus_profile
189
+ -C, --nocolor Disable ANSI coloring
190
+ -V, --debug Print extra output for debugging.
191
+ -h, --help Prints this help
192
+
193
+ ## COMMON OPTIONS
194
+
195
+ There are some common options that many commands support. They work the same way for each command.
196
+
197
+ -O, --option OPTION Option value in the format -O var="value" (deprecated soon in favor of first class options)
198
+ -N, --no-prompt Skip prompts. Use default values for all optional fields.
199
+ -j, --json JSON Output
200
+ -d, --dry-run Dry Run, print the API request instead of executing it
201
+ -r, --remote REMOTE Remote Appliance Name to use for this command. The active appliance is used by default.
202
+ -I, --insecure Allow for insecure HTTPS communication i.e. bad SSL certificate
203
+ -y, --yes Auto confirm, skip any 'Are you sure?' confirmations.
204
+ -r, --quiet No Output, when successful.
205
+
206
+ ## MORPHEUS COMMANDS
207
+
208
+ We divide morpheus into commands.
209
+ Every morpheus command may have 0-N sub-commands that it supports.
210
+ Commands generally map to the functionality provided in the Morpheus UI.
211
+
212
+ You can get help for any morpheus command by using the -h option.
213
+
214
+ The available commands and their options are also documented below.
215
+ ENDTEXT
216
+
217
+ terminal = Morpheus::Terminal.new($stdin, $stdout)
218
+ Morpheus::Logging::DarkPrinter.puts "appending command help `morpheus --help`" if Morpheus::Logging.debug?
219
+
220
+ $stdout.print "\n"
221
+ $stdout.print "## morpheus\n"
222
+ $stdout.print "\n"
223
+ $stdout.print "```\n"
224
+ exit_code, err = terminal.execute("--help")
225
+ $stdout.print "```\n"
226
+ $stdout.print "\n"
227
+ # output help for every unhidden command
228
+ Morpheus::Cli::CliRegistry.all.keys.sort.each do |cmd|
229
+ cmd_klass = Morpheus::Cli::CliRegistry.instance.get(cmd)
230
+ cmd_instance = cmd_klass.new
231
+ Morpheus::Logging::DarkPrinter.puts "appending command help `morpheus #{cmd} --help`" if Morpheus::Logging.debug?
232
+ #help_cmd = "morpheus #{cmd} --help"
233
+ #help_output = `#{help_cmd}`
234
+ $stdout.print "\n"
235
+ $stdout.print "### morpheus #{cmd}\n"
236
+ $stdout.print "\n"
237
+ $stdout.print "```\n"
238
+ begin
239
+ cmd_instance.handle(["--help"])
240
+ rescue SystemExit => err
241
+ raise err unless err.success?
242
+ end
243
+ $stdout.print "```\n"
244
+ subcommands = cmd_klass.subcommands
245
+ if subcommands && subcommands.size > 0
246
+ subcommands.sort.each do |subcommand, subcommand_method|
247
+ Morpheus::Logging::DarkPrinter.puts "appending command help `morpheus #{cmd} #{subcommand} --help`" if Morpheus::Logging.debug?
248
+ $stdout.print "\n"
249
+ $stdout.print "#### morpheus #{cmd} #{subcommand}\n"
250
+ $stdout.print "\n"
251
+ $stdout.print "```\n"
252
+ begin
253
+ cmd_instance.handle([subcommand, "--help"])
254
+ rescue SystemExit => err
255
+ raise err unless err.success?
256
+ end
257
+ $stdout.print "```\n"
258
+ # $stdout.print "\n"
259
+ end
260
+ end
261
+ $stdout.print "\n"
262
+ end
263
+
264
+ $stdout.print <<-ENDTEXT
265
+
266
+ ## ENVIRONMENT VARIABLES
267
+
268
+ Morpheus has only one environment variable that it uses.
269
+
270
+ ### MORPHEUS_CLI_HOME
271
+
272
+ The **MORPHEUS_CLI_HOME** variable is where morpheus CLI stores its configuration files.
273
+ This can be set to allow a single system user to maintain many different configurations
274
+ If the directory does not exist, morpheus will attempt to create it.
275
+
276
+ The default home directory is **$HOME/.morpheus**
277
+
278
+ To see how this works, run the following:
279
+
280
+ ```shell
281
+ MORPHEUS_CLI_HOME=~/.morpheus_test morpheus shell
282
+ ```
283
+
284
+ Now, in your new morpheus shell, you can see that it is a fresh environment.
285
+ There are no remote appliances configured.
286
+
287
+ ```shell
288
+ morpheus> remote list
289
+
290
+ Morpheus Appliances
291
+ ==================
292
+
293
+ You have no appliances configured. See the `remote add` command.
294
+
295
+ ```
296
+
297
+ You can use this to create isolated environments (sandboxes), within which to execute your morpheus commands.
298
+
299
+ ```shell
300
+ export MORPHEUS_CLI_HOME=~/morpheus_test
301
+ morpheus remote add myremote https://testmorpheusappliance.mycompany.com --insecure
302
+ morpheus instances list
303
+ ```
304
+
305
+ Morpheus saves the remote appliance information, including api access tokens,
306
+ to the $MORPHEUS_HOME_DIRECTORY. These files are saved with file permissions **6000**.
307
+ So, only one system user should be allowed to execute morpheus with that home directory.
308
+ See [Configuration](#Configuration) for more information on the files morpheus reads and writes.
309
+
310
+ ## CONFIGURATION
311
+
312
+ Morpheus reads and writes several configuration files within the $MORPHEUS_CLI_HOME directory.
313
+
314
+ **Note:** These files are maintained by the program. It is not recommended for you to manipulate them.
315
+
316
+ ### appliances file
317
+
318
+ The `appliances` YAML file contains a list of known appliances, keyed by name.
319
+
320
+ Example:
321
+ ```yaml
322
+ :qa:
323
+ :host: https://qa.mycoolsite.com
324
+ :active: true
325
+ :production:
326
+ :host: https://morpheus.mycoolsite.com
327
+ :active: false
328
+ ```
329
+
330
+ ### credentials file
331
+
332
+ The `.morpheus/credentials` YAML file contains access tokens for each known appliance.
333
+
334
+ ### groups file
335
+
336
+ The `.morpheus/groups` YAML file contains the active group information for each known appliance.
337
+
338
+
339
+ ## Startup scripts
340
+
341
+ When Morpheus starts, it executes the commands in a couple of dot files.
342
+
343
+ These scripts are written in morpheus commands, not bash, so they can only execute morpheus commands and aliases.
344
+
345
+ ### .morpheus_profile file
346
+
347
+ It looks for `$MORPHEUS_CLI_HOME/.morpheus_profile`, and reads and executes it (if it exists).
348
+
349
+ This may be inhibited by using the `--noprofile` option.
350
+
351
+ ### .morpheusrc file
352
+
353
+ When started as an interactive shell with the `morpheus shell` command,
354
+ Morpheus reads and executes `$MORPHEUS_CLI_HOME/.morpheusrc` (if it exists). This may be inhibited by using the `--norc` option.
355
+
356
+ An example startup script might look like this:
357
+
358
+ ```
359
+ # .morpheusrc
360
+
361
+ # aliases
362
+ alias our-instances='instances list -c "Our Cloud"'
363
+
364
+ # switch to our appliance that we created with `remote add morphapp1`
365
+ remote use morphapp1
366
+
367
+ # greeting
368
+ echo "Welcome back human, have fun!"
369
+
370
+ # print current user information
371
+ whoami
372
+
373
+ # print the list of instances in our cloud
374
+ our-instances
375
+
376
+ ```
377
+
378
+ ENDTEXT
379
+
380
+ ensure
381
+ manpage.close if manpage
382
+ $stdout = previous_stdout if previous_stdout
383
+ end
384
+
385
+ return true
386
+ end
387
+
388
+ end