class Kumogata2::CLI::OptionParser

Constants

COMMANDS
DEFAULT_OPTIONS
DEFAULT_OPTION_RETRY_LIMIT

Public Class Methods

parse!(argv) click to toggle source
# File lib/kumogata2/cli/option_parser.rb, line 78
def parse!(argv)
  self.new.parse!(argv)
end

Public Instance Methods

parse!(argv) click to toggle source
# File lib/kumogata2/cli/option_parser.rb, line 83
def parse!(argv)
  command = nil
  arguments = nil
  # https://github.com/aws/aws-sdk-ruby/blob/v2.3.11/aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb#L18
  region_keys = %w(AWS_REGION AMAZON_REGION AWS_DEFAULT_REGION)
  options = { aws: { region: ENV.values_at(*region_keys).compact.first,
              retry_limit: DEFAULT_OPTION_RETRY_LIMIT } }

  opt = ::OptionParser.new
  opt.summary_width = 65535
  set_usage!(opt)

  opt.on('-k', '--access-key ACCESS_KEY') {|v| options[:aws][:access_key_id]     = v }
  opt.on('-s', '--secret-key SECRET_KEY') {|v| options[:aws][:secret_access_key] = v }
  opt.on('-r', '--region REGION')         {|v| options[:aws][:region]            = v }
  opt.on('',   '--retry-limit LIMIT')     {|v| options[:aws][:retry_limit]       = v }

  opt.on('', '--profile PROFILE') do |v|
    options[:aws][:credentials] ||= {}
    options[:aws][:credentials][:profile_name] = v
  end

  opt.on('', '--credentials-path PATH') do |v|
    options[:aws][:credentials] ||= {}
    options[:aws][:credentials][:path] = v
  end

  plugin_exts = Kumogata2::Plugin.plugins.flat_map(&:ext).uniq
  opt.on(''  , '--output-format FORMAT', plugin_exts) do |v|
    options[:output_format] = v
  end

  opt.on('-p', '--parameters KEY_VALUES', Array) {|v| options[:parameters]              = v }
  opt.on('-j', '--json-parameters JSON')         {|v| options[:json_parameters]         = v }
  opt.on(''  , '--[no-]deletion-policy-retain')  {|v| options[:deletion_policy_retain]  = v }

  {
    disable_rollback: :boolean,
    timeout_in_minutes: Integer,
    notification_arns: Array,
    capabilities: Array,
    resource_types: Array,
    on_failure: nil,
    stack_policy_body: nil,
    stack_policy_url: nil,
    use_previous_template: :boolean,
    stack_policy_during_update_body: nil,
    stack_policy_during_update_url: nil,
    tags: Array,
  }.each do |key, type|
    opt_str = key.to_s.gsub('_', '-')
    opt_val = key.to_s.upcase

    case type
    when :boolean
      opt.on('', "--[no-]#{opt_str}") {|v| options[key] = v }
    when nil
      opt.on('', "--#{opt_str} #{opt_val}") {|v| options[key] = v }
    else
      opt.on('', "--#{opt_str} #{opt_val}", type) {|v| options[key] = v }
    end
  end

  opt.on(''  , '--result-log PATH')         {|v| options[:result_log]       = v }
  opt.on(''  , '--command-result-log PATH') {|v| options[:command]          = v }
  opt.on(''  , '--[no-]detach')             {|v| options[:detach]           = v }
  opt.on(''  , '--[no-]force')              {|v| options[:force]            = v }
  opt.on(''  , '--[no-]color')              {|v| options[:color]            = v }
  opt.on(''  , '--[no-]ignore-all-space')   {|v| options[:ignore_all_space] = v }
  opt.on(''  , '--[no-]debug')              {|v| options[:debug]            = v }

  opt.parse!

  unless (command = argv.shift)
    puts opt.help
    exit_parse!(1)
  end

  orig_command = command
  command = command.gsub('-', '_').to_sym
  command = find_command(command)

  unless command
    raise "Unknown command: #{orig_command}"
  end

  arguments = argv.dup
  validate_arguments(command, arguments)

  options = DEFAULT_OPTIONS.merge(options)
  options = Hashie::Mash.new(options)

  if options[:aws][:credentials]
    credentials = Aws::SharedCredentials.new(options[:aws][:credentials])
    options[:aws][:credentials] = credentials
  end

  Aws.config.update(options[:aws].dup)
  options = Hashie::Mash.new(options)

  String.colorize = options.color?
  Diffy::Diff.default_format = options.color? ? :color : :text

  if options.debug?
    Kumogata2::Logger.instance.set_debug(options.debug?)

    Aws.config.update(
      http_wire_trace: true,
      logger: Kumogata2::Logger.instance
    )
  end

  update_parameters(options)
  output = COMMANDS.fetch(command).fetch(:output, true)

  options.command = command
  options.arguments = arguments
  options.output_result = output

  [command, arguments, options, output]
end

Private Instance Methods

arguments_to_message(arguments) click to toggle source
# File lib/kumogata2/cli/option_parser.rb, line 256
def arguments_to_message(arguments)
  arguments.map {|i| i.to_s.sub(/(.+)\?\z/) { "[#{$1}]" }.upcase }.join(' ')
end
exit_parse!(exit_code) click to toggle source
# File lib/kumogata2/cli/option_parser.rb, line 217
def exit_parse!(exit_code)
  exit(exit_code)
end
find_command(command) click to toggle source
# File lib/kumogata2/cli/option_parser.rb, line 207
def find_command(command)
  selected = COMMANDS.keys.select {|i| i =~ /\A#{command}/ }

  if selected.length == 1
    selected.first
  else
    nil
  end
end
set_usage!(opt) click to toggle source
# File lib/kumogata2/cli/option_parser.rb, line 221
def set_usage!(opt)
  opt.banner = "Usage: kumogata2 <command> [args] [options]"
  opt.separator ''
  opt.separator 'Commands:'

  cmd_max_len = COMMANDS.keys.map {|i| i.to_s.length }.max

  cmd_arg_descs = COMMANDS.map do |command, attributes|
    command = command.to_s.gsub('_', '-')
    description = attributes.fetch(:description)
    arguments = attributes.fetch(:arguments)

    [
      '%-*s %s' % [cmd_max_len, command, arguments_to_message(arguments)],
      description,
    ]
  end

  cmd_arg_max_len = cmd_arg_descs.map {|i| i[0].length }.max

  opt.separator(cmd_arg_descs.map {|cmd_arg, desc|
    '  %-*s  %-s' % [cmd_arg_max_len, cmd_arg, desc]
  }.join("\n"))

  opt.separator ''
  opt.separator 'Plugins: '

  Kumogata2::Plugin.plugins.each do |plugin|
    opt.separator "  #{plugin.name}: #{plugin.ext.join(', ')}"
  end

  opt.separator ''
  opt.separator 'Options:'
end
update_parameters(options) click to toggle source
# File lib/kumogata2/cli/option_parser.rb, line 271
def update_parameters(options)
  parameters = {}

  (options.parameters || []).each do |i|
    key, value = i.split('=', 2)
    parameters[key] = value
  end

  if options.json_parameters
    parameters.merge!(JSON.parse(options.json_parameters))
  end

  options.parameters = parameters
end
validate_arguments(command, arguments) click to toggle source
# File lib/kumogata2/cli/option_parser.rb, line 260
def validate_arguments(command, arguments)
  expected = COMMANDS[command][:arguments] || []

  min = expected.count {|i| i.to_s !~ /\?\z/ }
  max = expected.length

  if arguments.length < min or max < arguments.length
    raise "Usage: kumogata2 #{command} #{arguments_to_message(expected)} [options]"
  end
end