# class Puppet::Configurer

### Attributes

instance[RW]

Puppet agent should only have one instance running, and we need a way to retrieve it.

compile_time[R]
environment[R]

### Public Class Methods

new() click to toggle source

Just so we can specify that we are “the” instance.

    # File lib/puppet/configurer.rb, line 54
    def initialize
      Puppet.settings.use(:main, :ssl, :agent)

      self.class.instance = self
      @running = false
      @splayed = false
      @environment = Puppet[:environment]
    end

to_s() click to toggle source

Provide more helpful strings to the logging that the Agent does

    # File lib/puppet/configurer.rb, line 20
    def self.to_s
      "Puppet configuration client"
    end

### Public Instance Methods

apply_catalog(catalog, options) click to toggle source

Retrieve (optionally) and apply a catalog. If a catalog is passed in the options, then apply that one, otherwise retrieve it.

    # File lib/puppet/configurer.rb, line 116
    def apply_catalog(catalog, options)
      report = options[:report]
      report.configuration_version = catalog.version
      report.environment = @environment

      benchmark(:notice, "Finished catalog run") do
        catalog.apply(options)
      end

      report.finalize_report
      report
    end

convert_catalog(result, duration) click to toggle source

Convert a plain resource catalog into our full host catalog.

    # File lib/puppet/configurer.rb, line 81
    def convert_catalog(result, duration)
      catalog = result.to_ral
      catalog.finalize
      catalog.retrieval_duration = duration
      catalog.write_class_file
      catalog.write_resource_file
      catalog
    end

execute_postrun_command() click to toggle source

    # File lib/puppet/configurer.rb, line 31
    def execute_postrun_command
      execute_from_setting(:postrun_command)
    end

execute_prerun_command() click to toggle source

    # File lib/puppet/configurer.rb, line 35
    def execute_prerun_command
      execute_from_setting(:prerun_command)
    end

get_facts(options) click to toggle source

    # File lib/puppet/configurer.rb, line 90
    def get_facts(options)
      download_plugins if options[:pluginsync]

      if Puppet::Resource::Catalog.indirection.terminus_class == :rest
        # This is a bit complicated.  We need the serialized and escaped facts,
        # and we need to know which format they're encoded in.  Thus, we
        # get a hash with both of these pieces of information.
        #
        # facts_for_uploading may set Puppet[:node_name_value] as a side effect
        return facts_for_uploading
      end
    end

init_storage() click to toggle source

Initialize and load storage

    # File lib/puppet/configurer.rb, line 40
    def init_storage
        Puppet::Util::Storage.load
        @compile_time ||= Puppet::Util::Storage.cache(:configuration)[:compile_time]
    rescue => detail
      Puppet.log_exception(detail, "Removing corrupt state file #{Puppet[:statefile]}: #{detail}")
      begin
        ::File.unlink(Puppet[:statefile])
        retry
      rescue => detail
        raise Puppet::Error.new("Cannot remove #{Puppet[:statefile]}: #{detail}")
      end
    end

prepare_and_retrieve_catalog(options, fact_options) click to toggle source

    # File lib/puppet/configurer.rb, line 103
    def prepare_and_retrieve_catalog(options, fact_options)
      # set report host name now that we have the fact
      options[:report].host = Puppet[:node_name_value]

      unless catalog = (options.delete(:catalog) || retrieve_catalog(fact_options))
        Puppet.err "Could not retrieve catalog; skipping run"
        return
      end
      catalog
    end

retrieve_catalog(fact_options) click to toggle source

Get the remote catalog, yo. Returns nil if no catalog can be found.

    # File lib/puppet/configurer.rb, line 64
    def retrieve_catalog(fact_options)
      fact_options ||= {}
      # First try it with no cache, then with the cache.
      unless (Puppet[:use_cached_catalog] and result = retrieve_catalog_from_cache(fact_options)) or result = retrieve_new_catalog(fact_options)
        if ! Puppet[:usecacheonfailure]
          Puppet.warning "Not using cache on failed catalog"
          return nil
        end
        result = retrieve_catalog_from_cache(fact_options)
      end

      return nil unless result

      convert_catalog(result, @duration)
    end

run(options = {}) click to toggle source

The code that actually runs the catalog. This just passes any options on to the catalog, which accepts :tags and :ignoreschedules.

    # File lib/puppet/configurer.rb, line 132
    def run(options = {})
      options[:report] ||= Puppet::Transaction::Report.new("apply")
      report = options[:report]
      init_storage

      Puppet::Util::Log.newdestination(report)
      begin
        unless Puppet[:node_name_fact].empty?
          fact_options = get_facts(options)
        end

        begin
          if node = Puppet::Node.indirection.find(Puppet[:node_name_value],
              :environment => @environment, :ignore_cache => true)
            if node.environment.to_s != @environment
              Puppet.warning "Local environment: \"#{@environment}\" doesn't match server specified node environment \"#{node.environment}\", switching agent to \"#{node.environment}\"."
              @environment = node.environment.to_s
              fact_options = nil
            end
          end
        rescue Puppet::Error, Net::HTTPError => detail
          Puppet.warning("Unable to fetch my node definition, but the agent run will continue:")
          Puppet.warning(detail)
        end

        fact_options = get_facts(options) unless fact_options

        unless catalog = prepare_and_retrieve_catalog(options, fact_options)
          return nil
        end

        # Here we set the local environment based on what we get from the
        # catalog. Since a change in environment means a change in facts, and
        # facts may be used to determine which catalog we get, we need to
        # rerun the process if the environment is changed.
        tries = 0
        while catalog.environment and not catalog.environment.empty? and catalog.environment != @environment
          if tries > 3
            raise Puppet::Error, "Catalog environment didn't stabilize after #{tries} fetches, aborting run"
          end
          Puppet.warning "Local environment: \"#{@environment}\" doesn't match server specified environment \"#{catalog.environment}\", restarting agent run with environment \"#{catalog.environment}\""
          @environment = catalog.environment
          return nil unless catalog = prepare_and_retrieve_catalog(options, fact_options)
          tries += 1
        end

        execute_prerun_command or return nil
        apply_catalog(catalog, options)
        report.exit_status
      rescue => detail
        Puppet.log_exception(detail, "Failed to apply catalog: #{detail}")
        return nil
      ensure
        execute_postrun_command or return nil
      end
    ensure
      # Between Puppet runs we need to forget the cached values.  This lets us
      # pick up on new functions installed by gems or new modules being added
      # without the daemon being restarted.
      Thread.current[:env_module_directories] = nil

      Puppet::Util::Log.close(report)
      send_report(report)
    end

save_last_run_summary(report) click to toggle source

    # File lib/puppet/configurer.rb, line 205
    def save_last_run_summary(report)
      mode = Puppet.settings.setting(:lastrunfile).mode
      Puppet::Util.replace_file(Puppet[:lastrunfile], mode) do |fh|
        fh.print YAML.dump(report.raw_summary)
      end
    rescue => detail
      Puppet.log_exception(detail, "Could not save last run local report: #{detail}")
    end

send_report(report) click to toggle source

    # File lib/puppet/configurer.rb, line 197
    def send_report(report)
      puts report.summary if Puppet[:summarize]
      save_last_run_summary(report)
      Puppet::Transaction::Report.indirection.save(report, nil, :environment => @environment) if Puppet[:report]
    rescue => detail
      Puppet.log_exception(detail, "Could not send report: #{detail}")
    end