def run
      # 1. Load configuration settings
      options = OptionsBag.load
      agent_id  = options[:identity]
      AgentConfig.root_dir = options[:root_dir]

      Log.program_name = 'RightLink'
      Log.facility = 'user'
      Log.log_to_file_only(options[:log_to_file_only])
      Log.init(agent_id, options[:log_path])
      Log.level = CookState.log_level
      # add an additional logger if the agent is set to log to an alternate 
      # location (install, operate, decommission, ...)
      Log.add_logger(::Logger.new(CookState.log_file)) if CookState.log_file

      Log.info("[cook] Process starting up with dev tags: [#{CookState.startup_tags.select { |tag| tag.include?(CookState::DEV_TAG_NAMESPACE)}.join(', ')}]")
      fail('Missing command server listen port') unless options[:listen_port]
      fail('Missing command cookie') unless options[:cookie]
      @client = CommandClient.new(options[:listen_port], options[:cookie])
      ShutdownRequestProxy.init(@client)

      # 2. Retrieve bundle
      input = gets.chomp
      begin
        platform = RightScale::Platform
        if platform.windows?
          bundle = MessageEncoder::SecretSerializer.new(InstanceState.identity, ENV[ExecutableSequenceProxy::DECRYPTION_KEY_NAME]).load(input)
        else
          bundle = MessageEncoder::Serializer.new.load(input)
        end
      rescue Exception => e
        fail('Invalid bundle', e.message)
      end

      fail('Missing bundle', 'No bundle to run') if bundle.nil?

      @thread_name = bundle.runlist_policy.thread_name if bundle.respond_to?(:runlist_policy) && bundle.runlist_policy
      @thread_name ||= RightScale::AgentConfig.default_thread_name
      options[:thread_name] = @thread_name

      # Chef state needs the server secret so it can encrypt state on disk.
      # The secret is the same for all instances of the server (i.e. is still
      # valid after stop and restart server).
      server_secret = bundle.server_secret || AgentConfig.default_server_secret
      ChefState.init(agent_id, server_secret, reset=false)

      # 3. Run bundle
      @@instance = self
      success = nil
      Log.debug("[cook] Thread name associated with bundle = #{@thread_name}")
      gatherer = ExternalParameterGatherer.new(bundle, options)
      sequence = ExecutableSequence.new(bundle)
      EM.threadpool_size = 1
      EM.error_handler do |e|
        Log.error("Execution failed", e, :trace)
        fail('Exception caught', "The following exception was caught during execution:\n  #{e.message}")
      end
      EM.run do
        begin
          AuditStub.instance.init(options)
          check_for_missing_inputs(bundle)
          gatherer.callback { EM.defer { sequence.run } }
          gatherer.errback { success = false; report_failure(gatherer) }
          sequence.callback { success = true; send_inputs_patch(sequence) }
          sequence.errback { success = false; report_failure(sequence) }

          EM.defer { gatherer.run }
        rescue Exception => e
          fail('Execution failed', Log.format("Execution failed", e, :trace))
        end
      end

    rescue Exception => e
      fail('Execution failed', Log.format("Run failed", e, :trace))

    ensure
      Log.info("[cook] Process stopping")
      exit(1) unless success
    end
def run
      # 1. Load configuration settings
      options = OptionsBag.load
      agent_id  = options[:identity]
      AgentConfig.root_dir = options[:root_dir]

      Log.program_name = 'RightLink'
      Log.facility = 'user'
      Log.log_to_file_only(options[:log_to_file_only])
      Log.init(agent_id, options[:log_path])
      Log.level = CookState.log_level
      # add an additional logger if the agent is set to log to an alternate 
      # location (install, operate, decommission, ...)
      Log.add_logger(::Logger.new(CookState.log_file)) if CookState.log_file

      Log.info("[cook] Process starting up with dev tags: [#{CookState.startup_tags.select { |tag| tag.include?(CookState::DEV_TAG_NAMESPACE)}.join(', ')}]")
      fail('Missing command server listen port') unless options[:listen_port]
      fail('Missing command cookie') unless options[:cookie]
      @client = CommandClient.new(options[:listen_port], options[:cookie])
      ShutdownRequestProxy.init(@client)

      # 2. Retrieve bundle
      input = gets.chomp
      begin
        platform = RightScale::Platform
        if platform.windows?
          bundle = MessageEncoder::SecretSerializer.new(InstanceState.identity, ENV[ExecutableSequenceProxy::DECRYPTION_KEY_NAME]).load(input)
        else
          bundle = MessageEncoder::Serializer.new.load(input)
        end
      rescue Exception => e
        fail('Invalid bundle', e.message)
      end

      fail('Missing bundle', 'No bundle to run') if bundle.nil?

      @thread_name = bundle.runlist_policy.thread_name if bundle.respond_to?(:runlist_policy) && bundle.runlist_policy
      @thread_name ||= RightScale::AgentConfig.default_thread_name
      options[:thread_name] = @thread_name

      # Chef state needs the server secret so it can encrypt state on disk.
      # The secret is the same for all instances of the server (i.e. is still
      # valid after stop and restart server).
      server_secret = bundle.server_secret || AgentConfig.default_server_secret
      ChefState.init(agent_id, server_secret, reset=false)

      # 3. Run bundle
      @@instance = self
      success = nil
      Log.debug("[cook] Thread name associated with bundle = #{@thread_name}")
      gatherer = ExternalParameterGatherer.new(bundle, options)
      sequence = ExecutableSequence.new(bundle)
      EM.threadpool_size = 1
      EM.error_handler do |e|
        Log.error("Execution failed", e, :trace)
        fail('Exception caught', "The following exception was caught during execution:\n  #{e.message}")
      end
      EM.run do
        begin
          AuditStub.instance.init(options)
          check_for_missing_inputs(bundle)
          gatherer.callback { EM.defer { sequence.run } }
          gatherer.errback { success = false; report_failure(gatherer) }
          sequence.callback { success = true; send_inputs_patch(sequence) }
          sequence.errback { success = false; report_failure(sequence) }

          EM.defer { gatherer.run }
        rescue Exception => e
          fail('Execution failed', Log.format("Execution failed", e, :trace))
        end
      end

    rescue Exception => e
      fail('Execution failed', Log.format("Run failed", e, :trace))

    ensure
      Log.info("[cook] Process stopping")
      exit(1) unless success
    end
Run bundle given in stdin