Class: Puppet::Configurer

Inherits:
Object show all
Extended by:
Util
Includes:
FactHandler, PluginHandler, Util
Defined in:
lib/puppet/configurer.rb

Defined Under Namespace

Modules: FactHandler, PluginHandler Classes: Downloader

Constant Summary

Constants included from Util

Util::AbsolutePathPosix, Util::AbsolutePathWindows, Util::DEFAULT_POSIX_MODE, Util::DEFAULT_WINDOWS_MODE

Constants included from Util::POSIX

Util::POSIX::LOCALE_ENV_VARS, Util::POSIX::USER_ENV_VARS

Constants included from Util::SymbolicFileMode

Util::SymbolicFileMode::SetGIDBit, Util::SymbolicFileMode::SetUIDBit, Util::SymbolicFileMode::StickyBit, Util::SymbolicFileMode::SymbolicMode, Util::SymbolicFileMode::SymbolicSpecialToBit

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util

absolute_path?, activerecord_version, benchmark, binread, chuser, classproxy, deterministic_rand, execfail, execpipe, execute, exit_on_fail, logmethods, memory, path_to_uri, pretty_backtrace, proxy, replace_file, safe_posix_fork, symbolizehash, thinmark, uri_to_path, which, withenv, withumask

Methods included from Util::POSIX

#get_posix_field, #gid, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid

Methods included from Util::SymbolicFileMode

#normalize_symbolic_mode, #symbolic_mode_to_int, #valid_symbolic_mode?

Methods included from PluginHandler

#download_plugins

Methods included from FactHandler

#facts_for_uploading, #find_facts

Constructor Details

#initializeConfigurer

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



55
56
57
58
59
60
61
62
63
# File 'lib/puppet/configurer.rb', line 55

def initialize
  Puppet.settings.use(:main, :ssl, :agent)

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

Class Attribute Details

.instanceObject

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



28
29
30
# File 'lib/puppet/configurer.rb', line 28

def instance
  @instance
end

Instance Attribute Details

#compile_timeObject (readonly)



18
19
20
# File 'lib/puppet/configurer.rb', line 18

def compile_time
  @compile_time
end

#environmentObject (readonly)



18
19
20
# File 'lib/puppet/configurer.rb', line 18

def environment
  @environment
end

Class Method Details

.to_sObject

Provide more helpful strings to the logging that the Agent does



21
22
23
# File 'lib/puppet/configurer.rb', line 21

def self.to_s
  "Puppet configuration client"
end

Instance Method Details

#apply_catalog(catalog, options) ⇒ Object

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



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/puppet/configurer.rb', line 118

def apply_catalog(catalog, options)
  report = options[:report]
  report.configuration_version = catalog.version
  report.transaction_uuid = @transaction_uuid
  report.environment = @environment

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

  report.finalize_report
  report
end

#convert_catalog(result, duration) ⇒ Object

Convert a plain resource catalog into our full host catalog.



83
84
85
86
87
88
89
90
# File 'lib/puppet/configurer.rb', line 83

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_commandObject



32
33
34
# File 'lib/puppet/configurer.rb', line 32

def execute_postrun_command
  execute_from_setting(:postrun_command)
end

#execute_prerun_commandObject



36
37
38
# File 'lib/puppet/configurer.rb', line 36

def execute_prerun_command
  execute_from_setting(:prerun_command)
end

#get_facts(options) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/puppet/configurer.rb', line 92

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

#get_transaction_uuidObject



132
133
134
# File 'lib/puppet/configurer.rb', line 132

def get_transaction_uuid
  { :transaction_uuid => @transaction_uuid }
end

#init_storageObject

Initialize and load storage



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/puppet/configurer.rb', line 41

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
    Puppet::FileSystem::File.unlink(Puppet[:statefile])
    retry
  rescue => detail
    raise Puppet::Error.new("Cannot remove #{Puppet[:statefile]}: #{detail}")
  end
end

#prepare_and_retrieve_catalog(options, query_options) ⇒ Object



105
106
107
108
109
110
111
112
113
114
# File 'lib/puppet/configurer.rb', line 105

def prepare_and_retrieve_catalog(options, query_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(query_options))
    Puppet.err "Could not retrieve catalog; skipping run"
    return
  end
  catalog
end

#retrieve_catalog(query_options) ⇒ Object

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



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/puppet/configurer.rb', line 66

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

  return nil unless result

  convert_catalog(result, @duration)
end

#run(options = {}) ⇒ Object

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



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/puppet/configurer.rb', line 139

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?
      query_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
          query_options = nil
        end
      end
    rescue SystemExit,NoMemoryError
      raise
    rescue Exception => detail
      Puppet.warning("Unable to fetch my node definition, but the agent run will continue:")
      Puppet.warning(detail)
    end

    query_options = get_facts(options) unless query_options

    # add the transaction uuid to the catalog query options hash
    query_options.merge! get_transaction_uuid if query_options

    unless catalog = prepare_and_retrieve_catalog(options, query_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, query_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.
  $env_module_directories = nil

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

#save_last_run_summary(report) ⇒ Object



218
219
220
221
222
223
224
225
# File 'lib/puppet/configurer.rb', line 218

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) ⇒ Object



210
211
212
213
214
215
216
# File 'lib/puppet/configurer.rb', line 210

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