Module: RightScale::RainbowsAgentController

Defined in:
lib/right_infrastructure_agent/rainbows_agent_controller.rb

Overview

Controller for running an agent in a Rainbows Rails environment Dependent upon existing base configuration file for agents of the given type

Defined Under Namespace

Classes: NoConfigurationData

Constant Summary collapse

FORCED_OPTIONS =
{
  :format    => :secure,
  :daemonize => false
}

Class Method Summary collapse

Class Method Details

.start(agent_types, worker, logger, options = {}) { ... } ⇒ TrueClass

Start agent and create error tracker for its use Choose agent type from candidate types based on contents of configuration directory Assign agent name by using worker index to suffix agent type Agent is required to call Proc in :ready_proc option when it is ready to receive traffic

the configuration hash and returning the updated configuration hash, optional

Parameters:

  • agent_types (Array)

    for candidate agents

  • worker (Unicorn::Worker)

    created by rainbows for this worker process; worker index is contained in its :nr attribute; worker will not receive HTTP traffic until its :ready attribute is set to true

  • logger (Object)

    to use

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :cfg_dir (String)

    containing configuration for all agents

  • :prefix (String)

    to build agent identity

  • :base_id (String, Integer)

    to build agent identity, defaults to worker_index + 1

Yields:

  • Invoked immediately prior to storing configuration receiving one parameter containing

Returns:

  • (TrueClass)

    always true



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
# File 'lib/right_infrastructure_agent/rainbows_agent_controller.rb', line 54

def self.start(agent_types, worker, logger, options = {}, &block)
  RightSupport::Log::Mixin.default_logger = logger
  Log.force_logger(logger) if logger
  @worker_index = worker.nr
  agent_name = nil

  # Declare that router is not yet ready for HTTP traffic
  # The agent being started below is required to use :ready_proc option to declare when it is ready
  worker.ready = false

  # Need next_tick here to wait for rainbows worker to start EventMachine
  EM.next_tick do
    begin
      AgentConfig.cfg_dir = options[:cfg_dir]
      agent_type = pick_agent_type(agent_types)
      raise NoConfigurationData, "Deployment is missing configuration file for any agents of type " +
                                 "#{agent_types.inspect} in #{AgentConfig.cfg_dir}; need to run rad!" unless agent_type

      # Configure agent
      agent_name = form_agent_name(agent_type, worker_index)
      cfg = configure_agent(agent_type, agent_name, worker_index, options, &block)
      cfg.merge!(options.merge(FORCED_OPTIONS))
      cfg[:agent_name] = agent_name

      require File.expand_path(File.join(AgentConfig.lib_dir, 'router_agent')) if agent_type == "router"

      # Initialize error tracking
      agent_class = (agent_type == "router") ? RouterAgent : InfrastructureAgent
      trace_level = defined?(agent_class::TRACE_LEVEL) ? agent_class::TRACE_LEVEL : {}
      filter_params = defined?(agent_class::FILTER_PARAMS) ? agent_class::FILTER_PARAMS : {}
      tracker_options = {:shard_id => cfg[:shard_id], :trace_level => trace_level, :filter_params => filter_params}
      if (endpoint = cfg[:airbrake_endpoint]) && (api_key = cfg[:airbrake_api_key])
        tracker_options[:airbrake_endpoint] = endpoint
        tracker_options[:airbrake_api_key] = api_key
      elsif defined?(Skeletor) && Skeletor::Deployer.config["error_handling"].respond_to?(:[]) &&
          (endpoint = Skeletor::Deployer.config["error_handling"]["airbrake_endpoint"]) &&
          (api_key = Skeletor::Deployer.config["error_handling"]["airbrake_api_key"])
        tracker_options[:airbrake_endpoint] = endpoint
        tracker_options[:airbrake_api_key] = api_key
      end
      ErrorTracker.init(self, agent_name, tracker_options)

      # Start the agent
      Log.info("Starting #{agent_name} agent with the following options:")
      cfg.inject([]) do |t, (k, v)|
        t << "-  #{k}: #{k.to_s =~ /pass|auth/ ? "<hidden>" : (v.respond_to?(:each) ? v.inspect : v)}"
      end.sort.each { |l| Log.info(l) }
      @agent = agent_class.start(cfg.merge(:ready_proc => Proc.new { worker.ready = true }))

    rescue PidFile::AlreadyRunning
      Log.error("#{agent_name} already running") rescue nil
      EM.stop
    rescue NoConfigurationData => e
      Log.error(e.message) rescue nil
      ErrorTracker.notify(e, nil, self, self)
      EM.stop
    rescue Exception => e
      Log.error("Failed to start #{agent_name} agent", e, :trace) rescue nil
      ErrorTracker.notify(e, nil, self, self)
      EM.stop
    end
  end
  true
end

.stopTrueClass

Stop agent by telling it to terminate Do not allow the agent termination to call EM.stop; instead defer that to rainbows to do after all connections are closed

Returns:

  • (TrueClass)

    always true



124
125
126
127
# File 'lib/right_infrastructure_agent/rainbows_agent_controller.rb', line 124

def self.stop
  @agent.terminate {} if @agent
  true
end

.worker_indexInteger

Rainbows worker index

Returns:

  • (Integer)

    0-based worker index



31
32
33
# File 'lib/right_infrastructure_agent/rainbows_agent_controller.rb', line 31

def self.worker_index
  @worker_index
end