Module: Asger::CLI

Defined in:
lib/asger/cli.rb

Overview

Command line functionality for Asger.

Class Method Summary collapse

Class Method Details

.mainObject

Entry point called from bin/asger.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/asger/cli.rb', line 15

def self.main()
  opts = Trollop::options do
    opt :task_file,       "path to a task (Ruby file; pass in order of execution; % refers to the stock_scripts directory)",
                          :type => :string, :multi => true
    opt :parameter_file,  "path to a params file (YAML or JSON; later files override earlier ones)",
                          :type => :string, :multi => true
    opt :queue_url,       "URL of the SQS queue to read from",
                          :type => :string
    opt :verbose,         "enables verbose logging",
                          :default => false
    opt :die_on_error,    "Terminates if an exception is thrown within the task runner.",
                          :default => true

    opt :delete_messages, 'Delete messages from the SQS queue after processing (off is useful for development).',
                          :default => true

    opt :aws_logging,     "Provides the Asger logger to AWS (use for deep debugging).", :default => false

    opt :shared_credentials, "Tells Asger to use shared credentials from '~/.aws/credentials'.", :type => :string
    opt :iam,             "Tells Asger to use IAM credentials.", :default => false
    opt :region,          'Specifies an AWS region.', :type => :string
  end

  logger = Logger.new($stderr)
  logger.info "Initializing Asger."

  logger.level = opts[:verbose] ? Logger::DEBUG : Logger::INFO

  if !opts[:queue_url]
    logger.error "--queue-url is required."
    exit(1)
  end
  if opts[:shared_credentials] && opts[:iam]
    logger.error "Only one of --shared-credentials and --iam can be used at a time."
    exit(1)
  end

  logger.warn "No tasks configured; Asger will run, but won't do much." \
    unless (opts[:task_file] && !opts[:task_file].empty?)

  param_files =
    opts[:parameter_file].map do |pf|
      logger.debug "Parsing parameter file '#{pf}'."
      case File.extname(pf)
        when ".json"
          JSON.parse(File.read(pf))
        when ".yaml"
          YAML.load(File.read(pf))
        else
          raise "Unrecognized parameter file: '#{pf}'."
      end
    end

  parameters = {}
  param_files.each { |p| parameters.deep_merge!(p) }

  credentials =
    if opts[:shared_credentials]
      logger.info "Using shared credentials '#{opts[:shared_credentials]}'."
      Aws::SharedCredentials.new(profile_name: opts[:shared_credentials])
    elsif opts[:iam]
      Aws::InstanceProfileCredentials.new
    else
      raise "No credentials found. Use --shared-credentials or --iam."
    end

  aws_logger = opts[:aws_logging] ? logger : nil
  sqs_client = Aws::SQS::Client.new(logger: aws_logger,
    region: opts[:region], credentials: credentials)
  ec2_client = Aws::EC2::Client.new(logger: aws_logger,
    region: opts[:region], credentials: credentials)
  asg_client = Aws::AutoScaling::Client.new(logger: aws_logger,
    region: opts[:region], credentials: credentials)


  stock_scripts_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "stock_scripts"))
  task_files = opts[:task_file].map { |f| f.gsub("%", stock_scripts_dir)}

  logger.info "Using task files:"
  task_files.each { |tf| logger.info " - #{tf}" }
  runner = Runner.new(logger: logger, aws_logger: aws_logger,
                      region: opts[:region], credentials: credentials,
                      queue_url: opts[:queue_url],
                      parameters: parameters,
                      task_files: task_files,
                      no_delete_messages: !opts[:delete_messages])

  logger.info "Beginning poll loop."
  loop do
    begin
      runner.poll
    rescue StandardError => err
      logger.error "Encountered an error."
      logger.error "#{err.class.name}: #{err.message}"
      err.backtrace.each { |bt| logger.error bt }

      if opts[:die_on_error]
        raise err
      else
        logger.error "re-entering poll."
      end
    end
  end
end