class EC2Ctl::CLI

Constants

DEFAULT_OPTIONS
OPTION_FILE_NAME
OptionError

Public Instance Methods

run() click to toggle source
# File lib/ec2ctl/cli.rb, line 20
def run
  program :name,        self.class.to_s
  program :version,     VERSION
  program :description, "A small command line tool for managing EC2/ELB."

  global_option "-V", "--verbose",                                 "Debug output."
  global_option "-P", "--pretty",                                  "Pretty JSON output."
  global_option "-o", "--output #{EC2Ctl::Logger::VALID_FORMATS}", "Log output format."
  global_option "-p", "--profile PROFILE_NAME",                    "AWS profile name."
  global_option "-r", "--region REGION_NAME",                      "AWS region name."

  default_command :"ec2 list"

  command :"ec2 list" do |c|
    c.syntax      = "ec2ctl ec2 list"
    c.description = "List EC2 instances."

    ec2_options c

    c.option "-a", "--attributes KEY1,KEY2...",     Array,  "(Optional) The instance attribute keys to display."
    c.option "-C", "--count",                               "(Optional) Display instance attribute stats."
    c.option       "--platform-type Linux|Windows", String, "(Optional) Platform type: `Linux` or `Windows`. Default is `Linux`."
    c.option "-S", "--sort KEY",                    String, "(Optional) Sort instances by this attribute."
    c.option       "--private-key-file PATH",       String, "(Optional) Path to private key file."

    c.action do |args, options|
      invoke c, options do
        @client.ec2_list
      end
    end
  end

  command :"ec2 execute" do |c|
    c.syntax      = "ec2ctl ec2 execute"
    c.description = "Execute commands in the EC2 instances."

    ec2_options c
    ssm_options c

    c.action do |args, options|
      invoke c, options do
        mandatory options, :commands
        @client.ec2_execute
      end
    end
  end

  command :"elb list" do |c|
    c.syntax      = "ec2ctl elb list"
    c.description = "List load balancers."

    c.action do |args, options|
      invoke c, options do
        @client.elb_list
      end
    end
  end

  command :"elb status" do |c|
    c.syntax      = "ec2ctl elb status"
    c.description = "Show the load balancer's status."

    c.option "-b", "--load-balancer-name VALUE", String, "The name of the load balancer."

    c.action do |args, options|
      invoke c, options do
        mandatory options, :load_balancer_name
        @client.elb_status
      end
    end
  end

  command :"elb attach" do |c|
    c.syntax      = "ec2ctl elb attach"
    c.description = "Attach the instances to the load balancer."

    c.option "-b", "--load-balancer-name VALUE",     String, "The name of the load balancer."
    c.option "-i", "--instance-ids STRING1,STRING2", Array,   "(Optional) The IDs of the instances to attach."

    c.action do |args, options|
      invoke c, options do
        mandatory options, :load_balancer_name, :instance_ids
        @client.elb_attach
      end
    end
  end

  command :"elb detach" do |c|
    c.syntax      = "ec2ctl elb detach"
    c.description = "Detach the instances from the load balancer."

    c.option "-b", "--load-balancer-name VALUE",     String, "The name of the load balancer."
    c.option "-i", "--instance-ids STRING1,STRING2", Array,   "(Optional) The IDs of the instances to detach."

    c.action do |args, options|
      invoke c, options do
        mandatory options, :load_balancer_name, :instance_ids
        @client.elb_detach
      end
    end
  end

  command :"elb execute" do |c|
    c.syntax      = "ec2ctl elb execute"
    c.description = "Execute commands on instance(s) registered to a load balancer."

    elb_execute_options c

    c.action do |args, options|
      invoke c, options do
        mandatory options, :load_balancer_name, :commands
        @client.elb_execute
      end
    end
  end

  command :"elb graceful" do |c|
    c.syntax      = "ec2ctl elb graceful"
    c.description = "Sequencially deregister instance(s) from load balancer, execute commands, register it back to load balancer and wait until it's in `InService` state."

    elb_execute_options c

    c.action do |args, options|
      invoke c, options do
        mandatory options, :load_balancer_name, :commands
        @client.elb_graceful
      end
    end
  end

  run!
end

Private Instance Methods

aws_env() click to toggle source

only for debug output

# File lib/ec2ctl/cli.rb, line 207
def aws_env
  {
    AWS_ACCESS_KEY_ID:     ("#{ENV["AWS_ACCESS_KEY_ID"][0, 5]}..." if ENV["AWS_ACCESS_KEY_ID"]),
    AWS_SECRET_ACCESS_KEY: ("#{ENV["AWS_SECRET_ACCESS_KEY"][0, 5]}..." if ENV["AWS_SECRET_ACCESS_KEY"]),
    AWS_PROFILE:           ENV["AWS_PROFILE"],
    AWS_REGION:            ENV["AWS_REGION"],
  }
end
debug_init(options) click to toggle source
# File lib/ec2ctl/cli.rb, line 216
def debug_init(options)
  logger.debug options: options.__hash__
  logger.debug aws_env: aws_env
end
ec2_options(cmd) click to toggle source
# File lib/ec2ctl/cli.rb, line 250
def ec2_options(cmd)
  cmd.option "-f", "--filters KEY1=VALUE1,KEY2=VALUE2...", Array, "(Optional) The key-value pairs to filter instances."
  cmd.option "-s", "--search KEY1=VALUE1,KEY2=VALUE2...",  Array, "(Optional) The key-value pairs to search instances by Regexp."
  cmd.option "-i", "--instance-ids STRING1,STRING2",       Array, "(Optional) The IDs of the instances."
end
elb_execute_options(cmd) click to toggle source
# File lib/ec2ctl/cli.rb, line 221
def elb_execute_options(cmd)
  cmd.option "-b", "--load-balancer-name STRING",               String,  "The name of the load balancer."
  cmd.option       "--rolling-group-size INTEGER",              Integer, "(Optional) The count of instances to register/deregister/execute simultaneously."
  cmd.option       "--skip-draining-waits",                              "(Optional) Skip waiting connection draining after deregistering instances from load balancer."
  cmd.option       "--skip-inservice-waits",                             "(Optional) Skip waiting `InService` state after registering instances to load balancer."
  cmd.option       "--inservice-wait-timeout INTEGER",          Integer, "(Optional) The time in seconds for instances to be `InService` state after registering to load balancer."
  cmd.option "-i", "--instance-ids STRING1,STRING2",            Array,   "(Optional) The IDs of the instances. If specified, the commands will be executed only on these instances."

  ssm_options(cmd)
end
handle_global_options(opt) click to toggle source
# File lib/ec2ctl/cli.rb, line 268
def handle_global_options(opt)
  @verbose           = true        if opt.verbose
  @pretty            = true        if opt.pretty
  @output_format     = opt.output  if opt.output
  ENV["AWS_PROFILE"] = opt.profile if opt.profile
  ENV["AWS_REGION"]  = opt.region  if opt.region
end
handle_options(cmd, opt) click to toggle source
# File lib/ec2ctl/cli.rb, line 256
def handle_options(cmd, opt)
  o           = {}
  default_opt = DEFAULT_OPTIONS[cmd.name.intern]
  file_opt    = options_from_file[cmd.name.intern]

  o.update default_opt if default_opt
  o.update file_opt if file_opt

  opt.default o
  handle_global_options opt
end
init_client(options) click to toggle source
# File lib/ec2ctl/cli.rb, line 155
def init_client(options)
  global_opt = %i(
    verbose
    pretty
    output
    profile
    region
    trace
    version
    help
  )

  @client = EC2Ctl::Client.new options.__hash__.reject {|k, v| global_opt.include? k}.merge(logger: logger)
end
invoke(cmd, opt, &block) click to toggle source
# File lib/ec2ctl/cli.rb, line 178
def invoke(cmd, opt, &block)
  begin
    handle_options cmd, opt
    debug_init opt
    init_client opt
    block.call
  rescue => ex
    logger.error(
      error: {
        class:   ex.class,
        message: ex.message
      }
    )

    raise
  end
end
logger() click to toggle source
# File lib/ec2ctl/cli.rb, line 170
def logger
  @logger ||= EC2Ctl::Logger.new(
    output_format: (@output_format || :json),
    pretty:        @pretty,
    verbose:       @verbose,
  )
end
mandatory(options, *option_names) click to toggle source

e.g.

mandatory options, :load_balancer_name, :commands

# File lib/ec2ctl/cli.rb, line 200
def mandatory(options, *option_names)
  option_names.each do |option_name|
    fail OptionError, "Option `#{option_name}` is mandatory." if options.__send__(option_name).nil?
  end
end
options_from_file() click to toggle source
# File lib/ec2ctl/cli.rb, line 276
def options_from_file
  pathnames = [
    # Ruby < 2.3
    (
      a = []
      Pathname.new(Dir.pwd).ascend {|path| a.push path}
      a
    ),
    # Ruby >= 2.3
    # Pathname.new(Dir.pwd).ascend.to_a,
    Pathname.new(Dir.home),
  ].flatten.map do |pathname|
    pathname + OPTION_FILE_NAME
  end

  pathnames.each do |pathname|
    return JSON.parse(File.read(pathname), symbolize_names: true) if File.exists? pathname
  end

  {}
end
ssm_options(cmd) click to toggle source
# File lib/ec2ctl/cli.rb, line 232
def ssm_options(cmd)
  cmd.option "-c", "--commands 'STRING1','STRING2',...",        Array,   "The commands to execute."
  cmd.option       "--platform-type Linux|Windows",             String,  "(Optional) Platform type: `Linux` or `Windows`. Default is `Linux`."
  cmd.option       "--skip-ping-check",                                  "(Optional) Skip SSM ping check."
  cmd.option       "--skip-command-waits",                               "(Optional) Skip waiting command success."
  cmd.option       "--wait-interval INTEGER",                   Integer, "(Optional) Waiting interval."
  cmd.option       "--working-directory STRING",                String,  "(Optional) The path to the working directory on your instance."
  cmd.option       "--execution-timeout INTEGER",               Integer, "(Optional) The time in seconds for a command to be completed before it is considered to have failed. Default is 3600 (1 hour). Maximum is 28800 (8 hours)."
  cmd.option       "--timeout-seconds INTEGER",                 Integer, "(Optional) If this time is reached and the command has not already started executing, it will not execute."
  cmd.option       "--comment STRING",                          String,  "(Optional) User-specified information about the command, such as a brief description of what the command should do."
  cmd.option       "--output-s3-bucket-name STRING",            String,  "(Optional) The name of the S3 bucket where command execution responses should be stored."
  cmd.option       "--output-s3-key-prefix STRING",             String,  "(Optional) The directory structure within the S3 bucket where the responses should be stored."
  cmd.option       "--service-role-arn STRING",                 String,  "(Optional) The IAM role that SSM uses to send notifications."
  cmd.option       "--notification-arn STRING",                 String,  "(Optional) An Amazon Resource Name (ARN) for a Simple Notification Service (SNS) topic."
  cmd.option       "--notification-events STRING1,STRING2,...", Array,   "(Optional) The different events for which you can receive notifications."
  cmd.option       "--notification-type STRING",                String,  "(Optional) Command: Receive notification when the status of a command changes."
end