module Ncio::Support::OptionParsing
Support
methods intended to be mixed into the application class. These methods are specific to command line parsing. The model is [GLOBAL OPTIONS] SUBCOMMAND [SUBCOMMAND OPTIONS]
Configuration state parsed from options is intended to be stored in a @opts hash and injected into dependencies, like API instances.
Constants
- BANNER
- CACERT_DEFAULT
- CACERT_MSG
- CERT_MSG
- CONNECT_TIMEOUT_DEFAULT
- FILE_DEFAULT_MAP
Map is indexed by the subcommand
- KEY_MSG
- NAMES
Names used to look for the default client certificate
- SSLDIR
Attributes
Public Class Methods
# File lib/ncio/support/option_parsing.rb, line 172 def self.pem_exists?(name) File.exist?(SSLDIR + "/certs/#{name}.pem") end
Public Instance Methods
# File lib/ncio/support/option_parsing.rb, line 180 def cert_default SSLDIR + "/certs/#{certname}.pem" end
# File lib/ncio/support/option_parsing.rb, line 176 def certname NAMES.find { |n| Ncio::Support::OptionParsing.pem_exists?(n) } || NAMES.first end
# File lib/ncio/support/option_parsing.rb, line 184 def key_default SSLDIR + "/private_keys/#{certname}.pem" end
Map an array of hostnames separated by a colon. The left is the key of the map, the right is the value. The Hash returned is “smart” in that a key that does not exist will return a value matching the key.
@param [Array<String>] hostnames
@return [Hash<String, String>] Hash of hostnames, left as key, right as
value.
# File lib/ncio/support/option_parsing.rb, line 163 def map_hostnames(hostnames) smart_map = Hash.new { |_, key| key } hostnames.each_with_object(smart_map) do |pair, hsh| (k, v) = pair.split(':') hsh[k] = v hsh end end
Parse out the global options, the ones specified between the main executable and the subcommand argument.
Modifies argv as a side effect, shifting elements from the array until the first unknown option is found, which is assumed to be the subcommand name.
@return [Hash<Symbol, String>] Global options rubocop:disable Metrics/MethodLength, Metrics/AbcSize
# File lib/ncio/support/option_parsing.rb, line 59 def parse_global_options!(argv, env) semver = Ncio::VERSION host = Socket.gethostname cert_default = self.cert_default key_default = self.key_default Ncio::Trollop.options(argv) do stop_on_unknown version "ncio #{semver} (c) 2016 Jeff McCune" banner BANNER uri_dfl = env['NCIO_URI'] || "https://#{host}:4433/classifier-api/v1" opt :uri, 'Node Classifier service uri '\ '{NCIO_URI}', default: uri_dfl opt :cert, CERT_MSG, default: env['NCIO_CERT'] || cert_default opt :key, KEY_MSG, default: env['NCIO_KEY'] || key_default opt :cacert, CACERT_MSG, default: env['NCIO_CACERT'] || CACERT_DEFAULT log_msg = 'Log file to write to or keywords '\ 'STDOUT, STDERR {NCIO_LOGTO}' opt :logto, log_msg, default: env['NCIO_LOGTO'] || 'STDERR' opt :syslog, 'Log to syslog', default: true, conflicts: :logto opt :verbose, 'Set log level to INFO' opt :debug, 'Set log level to DEBUG' opt :retry_connections, 'Retry API connections, '\ 'e.g. waiting for the service to come online. '\ '{NCIO_RETRY_CONNECTIONS}', default: (env['NCIO_RETRY_CONNECTIONS'] == 'true') || false opt :connect_timeout, 'Retry <i> seconds if --retry-connections=true '\ '{NCIO_CONNECT_TIMEOUT}', default: env['NCIO_CONNECT_TIMEOUT'] || CONNECT_TIMEOUT_DEFAULT end end
Parse options using the argument vector and the environment hash as input. Option parsing occurs in two phases, first the global options are parsed. These are the options specified before the subcommand. The subcommand, if any, is matched, and subcommand specific options are then parsed from the remainder of the argument vector.
@param [Array] argv The argument vector, passed to the option parser.
@param [Hash] env The environment hash, passed to the option parser to
supply defaults not specified on the command line argument vector.
@return [Hash<Symbol, String>] options hash
# File lib/ncio/support/option_parsing.rb, line 39 def parse_options(argv, env) argv_copy = argv.dup opts = parse_global_options!(argv_copy, env) subcommand = parse_subcommand!(argv_copy) opts[:subcommand] = subcommand sub_opts = parse_subcommand_options!(subcommand, argv_copy, env) opts.merge!(sub_opts) opts end
Extract the subcommand, if any, from the arguments provided. Modifies argv as a side effect, shifting the subcommand name if it is present.
@return [String] The subcommand name, e.g. 'backup' or 'restore', or
false if no arguments remain in the argument vector.
# File lib/ncio/support/option_parsing.rb, line 97 def parse_subcommand!(argv) argv.shift || false end
Parse the subcommand options. This method branches out because each subcommand can have quite different options, unlike global options which are consistent across all invocations of the application.
Modifies argv as a side effect, shifting all options as things are parsed.
@return [Hash<Symbol, String>] Subcommand specific options hash rubocop:disable Metrics/MethodLength, Metrics/AbcSize
# File lib/ncio/support/option_parsing.rb, line 111 def parse_subcommand_options!(subcommand, argv, env) case subcommand when 'backup', 'restore' Ncio::Trollop.options(argv) do banner "Node Classification #{subcommand} options:" groups_msg = 'Operate against NC groups. See: https://goo.gl/QD6ZdW' opt :groups, groups_msg, default: true file_msg = 'File to operate against {NCIO_FILE} or STDOUT, STDERR' file_default = FILE_DEFAULT_MAP[subcommand] opt :file, file_msg, default: env['NCIO_FILE'] || file_default end when 'transform' opts = Ncio::Trollop.options(argv) do banner "Node Classification transformations\n"\ 'Note: Currently only Monolithic (All-in-one) deployments are '\ "supported.\n\nTransformation matches against class names "\ 'assigned to groups. Transformation of hostnames happen '\ 'against rules assigned to groups and class parameters for '\ "matching classes.\n\nOptions:" hostname_msg = 'Replace the fully qualified domain name on the '\ 'left with the right, separated with a : '\ 'e.g --hostname master1.acme.com:master2.acme.com' opt :class_matcher, 'Regexp matching classes assigned to groups. '\ 'Passed to Regexp.new()', default: '^puppet_enterprise' opt :input, 'Input file path or keywords STDIN, STDOUT, STDERR', default: 'STDIN' opt :output, 'Output file path or keywords STDIN, STDOUT, STDERR', default: 'STDOUT' opt :hostname, hostname_msg, type: :strings, multi: true, required: true end opts[:matcher] = Regexp.new(opts[:class_matcher]) if opts[:hostname_given] hsh = map_hostnames(opts[:hostname].flatten) opts.merge!(hostname_map: hsh) end else Ncio::Trollop.die "Unknown subcommand: #{subcommand.inspect}" end end
Reset the @opts instance variable by parsing @argv and @env. Operates against duplicate copies of the argument vector avoid side effects.
@return [Hash<Symbol, String>] Options hash
# File lib/ncio/support/option_parsing.rb, line 22 def reset_options! @opts = parse_options(argv, env) end