Class: Puppet::Configurer

Inherits:
Object show all
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

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

Returns a new instance of Configurer.



47
48
49
50
51
52
53
54
# File 'lib/puppet/configurer.rb', line 47

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

  @running = false
  @splayed = false
  @environment = Puppet[:environment]
  @transaction_uuid = SecureRandom.uuid
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.



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/puppet/configurer.rb', line 112

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

  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.



74
75
76
77
78
79
80
81
# File 'lib/puppet/configurer.rb', line 74

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



25
26
27
# File 'lib/puppet/configurer.rb', line 25

def execute_postrun_command
  execute_from_setting(:postrun_command)
end

#execute_prerun_commandObject



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

def execute_prerun_command
  execute_from_setting(:prerun_command)
end

#get_facts(options) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/puppet/configurer.rb', line 83

def get_facts(options)
  if options[:pluginsync]
    remote_environment_for_plugins = Puppet::Node::Environment.remote(@environment)
    download_plugins(remote_environment_for_plugins)
  end

  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_storageObject

Initialize and load storage



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/puppet/configurer.rb', line 34

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

#prepare_and_retrieve_catalog(options, query_options) ⇒ Object



99
100
101
102
103
104
105
106
107
108
# File 'lib/puppet/configurer.rb', line 99

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.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/puppet/configurer.rb', line 57

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.



127
128
129
130
131
132
133
134
135
136
137
138
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
# File 'lib/puppet/configurer.rb', line 127

def run(options = {})
  # We create the report pre-populated with default settings for
  # environment and transaction_uuid very early, this is to ensure
  # they are sent regardless of any catalog compilation failures or
  # exceptions.
  options[:report] ||= Puppet::Transaction::Report.new("apply", nil, @environment, @transaction_uuid)
  report = options[:report]
  init_storage

  Puppet::Util::Log.newdestination(report)

  begin
    unless Puppet[:node_name_fact].empty?
      query_options = get_facts(options)
    end

    # We only need to find out the environment to run in if we don't already have a catalog
    unless options[:catalog]
      begin
        if node = Puppet::Node.indirection.find(Puppet[:node_name_value],
            :environment => @environment, :ignore_cache => true, :transaction_uuid => @transaction_uuid,
            :fail_on_404 => 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
            report.environment = @environment
            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
    end

    query_options = get_facts(options) unless query_options

    # get_facts returns nil during puppet apply
    query_options ||= {}
    query_options[:transaction_uuid] = @transaction_uuid

    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
      report.environment = @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



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

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



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

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