class Morpheus::Cli::ManCommand
Public Class Methods
man_file_path()
click to toggle source
# File lib/morpheus/cli/commands/man_command.rb, line 11 def self.man_file_path File.join(Morpheus::Cli.home_directory, "CLI-Manual-#{Morpheus::Cli::VERSION}.md") end
Public Instance Methods
generate_manual(options={})
click to toggle source
def self.save_manual(fn, content)
# fn = Morpheus::Cli::ManCommand.man_file_path if !Dir.exist?(File.dirname(fn)) FileUtils.mkdir_p(File.dirname(fn)) end Morpheus::Logging::DarkPrinter.puts "saving manual to #{fn}" if Morpheus::Logging.debug? File.open(fn, 'w') {|f| f.write content.to_s } #Store FileUtils.chmod(0600, fn)
end
# File lib/morpheus/cli/commands/man_command.rb, line 167 def generate_manual(options={}) # todo: use pandoc or something else to convert the CLI-Manual.md to a man page # and install it, so the os command `man morpheus` will work too. fn = Morpheus::Cli::ManCommand.man_file_path if options[:outfile] fn = File.expand_path(options[:outfile]) if File.exist?(fn) && options[:overwrite] != true print_error "#{red}Output file '#{options[:outfile]}' already exists.#{reset}\n" print_error "#{red}Use --overwrite to overwrite the existing file.#{reset}\n" return 1, "output file already exists" end end if !Dir.exist?(File.dirname(fn)) FileUtils.mkdir_p(File.dirname(fn)) end Morpheus::Logging::DarkPrinter.puts "generating manual #{fn}" if Morpheus::Logging.debug? && !options[:quiet] File.open(fn, 'w') {|f| f.write("") } # clear file FileUtils.chmod(0600, fn) manpage = File.new(fn, 'w') # previous_stdout = $stdout # previous_stdout = STDOUT # $stdout = manpage begin manpage.print <<-ENDTEXT #{prog_name} v#{Morpheus::Cli::VERSION} ## NAME morpheus - the command line interface for interacting with the Morpheus appliance ## SYNOPSIS morpheus [command] [<args>] [options] ## DESCRIPTION Morpheus CLI This is a command line interface for managing a Morpheus Appliance. All communication with the remote appliance is done via the Morpheus API. Use the command `#{prog_name} remote add` to connect to your Morpheus appliance. To learn more, visit https://clidocs.morpheusdata.com To learn more about the Morpheus Appliance, visit https://www.morpheusdata.com To learn more about the Morpheus API, visit https://apidocs.morpheusdata.com ## GLOBAL OPTIONS There are several global options available. -v, --version Print the version. --noprofile Do not read and execute the personal initialization script .morpheus_profile -C, --nocolor Disable ANSI coloring -V, --debug Print extra output for debugging. -h, --help Print this help ## COMMON OPTIONS There are many common options that are supported by a most commands. -O, --option OPTION Option value in the format -O var="value" (deprecated soon in favor of first class options) -N, --no-prompt Skip prompts. Use default values for all optional fields. --payload FILE Payload from a local JSON or YAML file, skip all prompting --payload-dir DIRECTORY Payload from a local directory containing 1-N JSON or YAML files, skip all prompting --payload-json JSON Payload JSON, skip all prompting --payload-yaml YAML Payload YAML, skip all prompting -j, --json JSON Output -d, --dry-run Dry Run, print the API request instead of executing it --curl Dry Run to output API request as a curl command. --scrub Mask secrets in output, such as the Authorization header. For use with --curl and --dry-run. -r, --remote REMOTE Remote name. The current remote is used by default. --remote-url URL Remote url. This allows adhoc requests instead of using a configured remote. -T, --token TOKEN Access token for authentication with --remote. Saved credentials are used by default. -U, --username USERNAME Username for authentication. -P, --password PASSWORD Password for authentication. -I, --insecure Allow insecure HTTPS communication. i.e. bad SSL certificate. -H, --header HEADER Additional HTTP header to include with requests. --timeout SECONDS Timeout for api requests. Default is typically 30 seconds. -y, --yes Auto Confirm -q, --quiet No Output, do not print to stdout ## MORPHEUS COMMANDS The morpheus executable is divided into commands. Each morpheus command may have 0-N sub-commands that it supports. Commands generally map to the functionality provided in the Morpheus UI. You can get help for any morpheus command by using the -h option. The available commands and their options are documented below. ENDTEXT #terminal = Morpheus::Terminal.new($stdin, manpage) terminal = my_terminal terminal.with_stdout(manpage) do Morpheus::Logging::DarkPrinter.puts "appending command help `#{prog_name} --help`" if Morpheus::Logging.debug? && !options[:quiet] manpage.print "\n" manpage.print "## morpheus\n" manpage.print "\n" manpage.print "```\n" exit_code, err = terminal.execute("--help") manpage.print "```\n" manpage.print "\n" # output help for every command (that is not hidden) Morpheus::Cli::CliRegistry.all.keys.sort.each do |cmd| cmd_klass = Morpheus::Cli::CliRegistry.instance.get(cmd) cmd_instance = cmd_klass.new Morpheus::Logging::DarkPrinter.puts "appending command help `#{prog_name} #{cmd} --help`" if Morpheus::Logging.debug? && !options[:quiet] #help_cmd = "morpheus #{cmd} --help" #help_output = `#{help_cmd}` manpage.print "\n" manpage.print "### morpheus #{cmd}\n" manpage.print "\n" manpage.print "```\n" begin cmd_instance.handle(["--help"]) rescue SystemExit => err raise err unless err.success? end manpage.print "```\n" # subcommands = cmd_klass.subcommands subcommands = cmd_klass.visible_subcommands if subcommands && subcommands.size > 0 subcommands.sort.each do |subcommand, subcommand_method| Morpheus::Logging::DarkPrinter.puts "appending command help `#{prog_name} #{cmd} #{subcommand} --help`" if Morpheus::Logging.debug? && !options[:quiet] manpage.print "\n" manpage.print "#### morpheus #{cmd} #{subcommand}\n" manpage.print "\n" manpage.print "```\n" begin cmd_instance.handle([subcommand, "--help"]) rescue SystemExit => err raise err unless err.success? end manpage.print "```\n" # manpage.print "\n" end end manpage.print "\n" end manpage.print <<-ENDTEXT ## ENVIRONMENT VARIABLES Morpheus has only one environment variable that it uses. ### MORPHEUS_CLI_HOME The **MORPHEUS_CLI_HOME** variable is where morpheus CLI stores its configuration files. This can be set to allow a single system user to maintain many different configurations If the directory does not exist, morpheus will attempt to create it. The default home directory is **$HOME/.morpheus** To see how this works, run the following: ```shell MORPHEUS_CLI_HOME=~/.morpheus_test morpheus shell ``` Now, in your new morpheus shell, you can see that it is a fresh environment. There are no remote appliances configured. ```shell morpheus> remote list Morpheus Appliances ================== You have no appliances configured. See the `#{prog_name} remote add` command. ``` You can use this to create isolated environments (sandboxes), within which to execute your morpheus commands. ```shell export MORPHEUS_CLI_HOME=~/morpheus_test morpheus remote add demo https://demo-morpheus --insecure morpheus instances list ``` Morpheus saves the remote appliance information, including api access tokens, to the CLI home directory. These files are saved with file permissions **6000**. So, only one system user should be allowed to execute morpheus with that home directory. See [Configuration](#Configuration) for more information on the files morpheus reads and writes. ## CONFIGURATION Morpheus reads and writes several configuration files within the $MORPHEUS_CLI_HOME directory. **Note:** These files are maintained by the program. It is not recommended for you to manipulate them. ### appliances file The `appliances` YAML file contains a list of known appliances, keyed by name. Example: ```yaml :qa: :host: https://qa-morpheus :production: :host: https://production-morpheus ``` ### credentials file The `.morpheus/credentials` YAML file contains access tokens for each known appliance. ### groups file The `.morpheus/groups` YAML file contains the active group information for each known appliance. ## Startup scripts When Morpheus starts, it executes the commands in a couple of dot files. These scripts are written in morpheus commands, not bash, so they can only execute morpheus commands and aliases. ### .morpheus_profile file It looks for `$MORPHEUS_CLI_HOME/.morpheus_profile`, and reads and executes it (if it exists). This may be inhibited by using the `--noprofile` option. ### .morpheusrc file When started as an interactive shell with the `#{prog_name} shell` command, Morpheus reads and executes `$MORPHEUS_CLI_HOME/.morpheusrc` (if it exists). This may be inhibited by using the `--norc` option. An example startup script might look like this: ``` # .morpheusrc set-prompt "%cyan%username%reset@%magenta%remote %cyanmorpheus> %reset" version remote current echo "Welcome back %username" echo ``` ENDTEXT end # end with_stdout(manpage) ensure manpage.close if manpage # $stdout = previous_stdout if previous_stdout # this is needed to re-establish instance with STDOUT, STDIN #terminal = Morpheus::Terminal.new() end return 0, nil end
handle(args)
click to toggle source
# File lib/morpheus/cli/commands/man_command.rb, line 15 def handle(args) options = {} regenerate = false open_as_link = false # true please goto_wiki = false editor = @@default_editor #todo: windows if !$stdin.tty? editor = "cat" end # no editor for windows atm if Morpheus::Cli.windows? open_as_link = true end optparse = Morpheus::Cli::OptionParser.new do|opts| opts.banner = "Usage: morpheus man" opts.on('-w','--wiki', "Open the morpheus-cli wiki instead of the local man page") do goto_wiki = true end opts.on('-e','--editor EDITOR', "Specify which program to open the manual with. Default is '#{editor}'.") do |val| editor = val open_as_link = false end opts.on('-g','--generate', "Regenerate the manual file") do regenerate = true end opts.on('-o','--out FILE', "Write manual file to a custom location") do |val| options[:outfile] = val end opts.on('--overwrite', '--overwrite', "Overwrite output file if it already exists.") do |val| options[:overwrite] = true end opts.on('-q','--quiet', "Do not open manual, for use with the -g option.") do options[:quiet] = true end #build_common_options(opts, options, [:quiet]) # disable ANSI coloring opts.on('-C','--nocolor', "Disable ANSI coloring") do Term::ANSIColor::coloring = false end opts.on('-V','--debug', "Print extra output for debugging. ") do Morpheus::Logging.set_log_level(Morpheus::Logging::Logger::DEBUG) ::RestClient.log = Morpheus::Logging.debug? ? Morpheus::Logging::DarkPrinter.instance : nil end opts.on('-h', '--help', "Print this help" ) do puts opts exit end opts.footer = <<-EOT Open the morpheus manual located at #{Morpheus::Cli::ManCommand.man_file_path} The -g option can be used to regenerate the file. The --out FILE option be used to write the manual file to a custom location. EOT end optparse.parse!(args) verify_args!(args:args, optparse:optparse, count:0) if goto_wiki link = "https://github.com/gomorpheus/morpheus-cli/wiki/CLI-Manual" if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ system "start #{link}" elsif RbConfig::CONFIG['host_os'] =~ /darwin/ system "open #{link}" elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/ system "xdg-open #{link}" end return 0, nil end fn = Morpheus::Cli::ManCommand.man_file_path if options[:outfile] regenerate = true fn = File.expand_path(options[:outfile]) if File.directory?(fn) # if you give me a directory, could still work and use the default filename # fn = File.join(fn, "CLI-Manual-#{Morpheus::Cli::VERSION}.md") # raise_command_error "outfile is invalid. It is the name of an existing directory: #{fn}" print_error "#{red}Output file '#{fn}' is invalid.#{reset}\n" print_error "#{red}It is the name of an existing directory.#{reset}\n" return 1 end if File.exist?(fn) && options[:overwrite] != true print_error "#{red}Output file '#{fn}' already exists.#{reset}\n" print_error "#{red}Use --overwrite to overwrite the existing file.#{reset}\n" return 1 end end exit_code, err = 0, nil if regenerate || !File.exist?(fn) #Morpheus::Logging::DarkPrinter.puts "generating manual #{fn} ..." if Morpheus::Logging.debug? && !options[:quiet] exit_code, err = generate_manual(options) end if options[:quiet] return exit_code, err end Morpheus::Logging::DarkPrinter.puts "opening manual file #{fn}" if Morpheus::Logging.debug? && !options[:quiet] if open_as_link # windows only atm link = "file://#{fn}" if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/ system "start #{link}" elsif RbConfig::CONFIG['host_os'] =~ /darwin/ system "open #{link}" elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/ system "xdg-open #{link}" end return 0, nil else if editor if !system_command_available?(editor) raise_command_error "The editor program '#{editor}' is not available on your system." # puts_error "#{red}The editor program '#{editor}' is not available on your system.#{reset}" # return 1 end system("#{editor} #{fn}") else raise_command_error "Tell me how to open the manual file #{fn}. Try -e emacs or run export EDITOR=emacs" return 1 end end return 0, nil end
system_command_available?(cmd)
click to toggle source
determine if system command is available uses *nix’s ‘which` command. Prevents using dangerous commands rm,mv,passwd todo: support for Windows and PowerShell
# File lib/morpheus/cli/commands/man_command.rb, line 145 def system_command_available?(cmd) has_it = false begin cmd = cmd.strip.gsub("'",'') system("which '#{cmd}' > /dev/null 2>&1") has_it = $?.success? rescue => e raise e end return has_it end