Class: Puppet::Transaction
- Includes:
- Util, Util::Tagging
- Defined in:
- lib/puppet/transaction.rb
Defined Under Namespace
Classes: Event, EventManager, Report, ResourceHarness
Instance Attribute Summary collapse
-
#catalog ⇒ Object
Returns the value of attribute catalog.
-
#component ⇒ Object
Returns the value of attribute component.
-
#configurator ⇒ Object
Returns the value of attribute configurator.
-
#event_manager ⇒ Object
readonly
Routes and stores any events and subscriptions.
-
#ignoreschedules ⇒ Object
Returns the value of attribute ignoreschedules.
-
#report ⇒ Object
readonly
The report, once generated.
-
#resource_harness ⇒ Object
readonly
Handles most of the actual interacting with resources.
-
#sorted_resources ⇒ Object
Returns the value of attribute sorted_resources.
Instance Method Summary collapse
- #add_resource_status(status) ⇒ Object
-
#add_times(hash) ⇒ Object
Add some additional times for reporting.
-
#any_failed? ⇒ Boolean
Are there any failed resources in this transaction?.
-
#apply(resource, ancestor = nil) ⇒ Object
Apply all changes for a resource.
-
#changed? ⇒ Boolean
Find all of the changed resources.
- #eval_children_and_apply_resource(resource, ancestor = nil) ⇒ Object
-
#eval_generate(resource) ⇒ Object
See if the resource generates new resources at evaluation time.
-
#eval_resource(resource, ancestor = nil) ⇒ Object
Evaluate a single resource.
-
#evaluate ⇒ Object
This method does all the actual work of running a transaction.
- #events ⇒ Object
- #failed?(resource) ⇒ Boolean
-
#failed_dependencies?(resource) ⇒ Boolean
Does this resource have any failed dependencies?.
-
#generate ⇒ Object
Collect any dynamically generated resources.
-
#generate_additional_resources(resource, method) ⇒ Object
A general method for recursively generating new resources from a resource.
- #handle_qualified_tags(qualified) ⇒ Object
-
#ignore_tags? ⇒ Boolean
Should we ignore tags?.
-
#initialize(catalog, report = nil) ⇒ Transaction
constructor
this should only be called by a Puppet::Type::Component resource now and it should only receive an array.
-
#make_parent_child_relationship(resource, children) ⇒ Object
Copy an important relationships from the parent to the newly-generated child resource.
-
#missing_tags?(resource) ⇒ Boolean
Is this resource tagged appropriately?.
-
#prefetch ⇒ Object
Prefetch any providers that support it.
-
#prepare ⇒ Object
Prepare to evaluate the resources in a transaction.
- #relationship_graph ⇒ Object
- #resource_status(resource) ⇒ Object
-
#scheduled?(resource) ⇒ Boolean
Is the resource currently scheduled?.
-
#skip?(resource) ⇒ Boolean
Should this resource be skipped?.
-
#stop_processing? ⇒ Boolean
Wraps application run state check to flag need to interrupt processing.
-
#tags ⇒ Object
The tags we should be checking.
Methods included from Util::Tagging
Methods included from Util
activerecord_version, benchmark, chuser, classproxy, #execfail, #execpipe, execute, logmethods, memory, proxy, recmkdir, secure_open, symbolize, symbolizehash, symbolizehash!, synchronize_on, thinmark, #threadlock, which, withumask
Methods included from Util::POSIX
#get_posix_field, #gid, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid
Constructor Details
#initialize(catalog, report = nil) ⇒ Transaction
this should only be called by a Puppet::Type::Component resource now and it should only receive an array
223 224 225 226 227 228 |
# File 'lib/puppet/transaction.rb', line 223 def initialize(catalog, report = nil) @catalog = catalog @report = report || Report.new("apply", catalog.version) @event_manager = Puppet::Transaction::EventManager.new(self) @resource_harness = Puppet::Transaction::ResourceHarness.new(self) end |
Instance Attribute Details
#catalog ⇒ Object
Returns the value of attribute catalog.
14 15 16 |
# File 'lib/puppet/transaction.rb', line 14 def catalog @catalog end |
#component ⇒ Object
Returns the value of attribute component.
14 15 16 |
# File 'lib/puppet/transaction.rb', line 14 def component @component end |
#configurator ⇒ Object
Returns the value of attribute configurator.
15 16 17 |
# File 'lib/puppet/transaction.rb', line 15 def configurator @configurator end |
#event_manager ⇒ Object (readonly)
Routes and stores any events and subscriptions.
21 22 23 |
# File 'lib/puppet/transaction.rb', line 21 def event_manager @event_manager end |
#ignoreschedules ⇒ Object
Returns the value of attribute ignoreschedules.
14 15 16 |
# File 'lib/puppet/transaction.rb', line 14 def ignoreschedules @ignoreschedules end |
#report ⇒ Object (readonly)
The report, once generated.
18 19 20 |
# File 'lib/puppet/transaction.rb', line 18 def report @report end |
#resource_harness ⇒ Object (readonly)
Handles most of the actual interacting with resources
24 25 26 |
# File 'lib/puppet/transaction.rb', line 24 def resource_harness @resource_harness end |
#sorted_resources ⇒ Object
Returns the value of attribute sorted_resources.
15 16 17 |
# File 'lib/puppet/transaction.rb', line 15 def sorted_resources @sorted_resources end |
Instance Method Details
#add_resource_status(status) ⇒ Object
270 271 272 |
# File 'lib/puppet/transaction.rb', line 270 def add_resource_status(status) report.add_resource_status status end |
#add_times(hash) ⇒ Object
Add some additional times for reporting
35 36 37 38 39 |
# File 'lib/puppet/transaction.rb', line 35 def add_times(hash) hash.each do |name, num| report.add_times(name, num) end end |
#any_failed? ⇒ Boolean
Are there any failed resources in this transaction?
42 43 44 |
# File 'lib/puppet/transaction.rb', line 42 def any_failed? report.resource_statuses.values.detect { |status| status.failed? } end |
#apply(resource, ancestor = nil) ⇒ Object
Apply all changes for a resource
47 48 49 50 51 52 53 |
# File 'lib/puppet/transaction.rb', line 47 def apply(resource, ancestor = nil) status = resource_harness.evaluate(resource) add_resource_status(status) event_manager.queue_events(ancestor || resource, status.events) unless status.failed? rescue => detail resource.err "Could not evaluate: #{detail}" end |
#changed? ⇒ Boolean
Find all of the changed resources.
56 57 58 |
# File 'lib/puppet/transaction.rb', line 56 def changed? report.resource_statuses.values.find_all { |status| status.changed }.collect { |status| catalog.resource(status.resource) } end |
#eval_children_and_apply_resource(resource, ancestor = nil) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/puppet/transaction.rb', line 98 def eval_children_and_apply_resource(resource, ancestor = nil) resource_status(resource).scheduled = true # We need to generate first regardless, because the recursive # actions sometimes change how the top resource is applied. children = eval_generate(resource) if ! children.empty? and resource.depthfirst? children.each do |child| # The child will never be skipped when the parent isn't eval_resource(child, ancestor || resource) end end # Perform the actual changes apply(resource, ancestor) if ! children.empty? and ! resource.depthfirst? children.each do |child| eval_resource(child, ancestor || resource) end end end |
#eval_generate(resource) ⇒ Object
See if the resource generates new resources at evaluation time.
82 83 84 |
# File 'lib/puppet/transaction.rb', line 82 def eval_generate(resource) generate_additional_resources(resource, :eval_generate) end |
#eval_resource(resource, ancestor = nil) ⇒ Object
Evaluate a single resource.
87 88 89 90 91 92 93 94 95 96 |
# File 'lib/puppet/transaction.rb', line 87 def eval_resource(resource, ancestor = nil) if skip?(resource) resource_status(resource).skipped = true else eval_children_and_apply_resource(resource, ancestor) end # Check to see if there are any events queued for this resource event_manager.process_events(resource) end |
#evaluate ⇒ Object
This method does all the actual work of running a transaction. It collects all of the changes, executes them, and responds to any necessary events.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/puppet/transaction.rb', line 125 def evaluate prepare Puppet.info "Applying configuration version '#{catalog.version}'" if catalog.version @sorted_resources.each do |resource| next if stop_processing? if resource.is_a?(Puppet::Type::Component) Puppet.warning "Somehow left a component in the relationship graph" next end ret = nil seconds = thinmark do ret = eval_resource(resource) end resource.info "valuated in %0.2f seconds" % seconds if Puppet[:evaltrace] and @catalog.host_config? ret end Puppet.debug "Finishing transaction #{object_id}" end |
#events ⇒ Object
148 149 150 |
# File 'lib/puppet/transaction.rb', line 148 def events event_manager.events end |
#failed?(resource) ⇒ Boolean
152 153 154 |
# File 'lib/puppet/transaction.rb', line 152 def failed?(resource) s = resource_status(resource) and s.failed? end |
#failed_dependencies?(resource) ⇒ Boolean
Does this resource have any failed dependencies?
157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/puppet/transaction.rb', line 157 def failed_dependencies?(resource) # First make sure there are no failed dependencies. To do this, # we check for failures in any of the vertexes above us. It's not # enough to check the immediate dependencies, which is why we use # a tree from the reversed graph. found_failed = false relationship_graph.dependencies(resource).each do |dep| next unless failed?(dep) resource.notice "Dependency #{dep} has failures: #{resource_status(dep).failed}" found_failed = true end found_failed end |
#generate ⇒ Object
Collect any dynamically generated resources. This method is called before the transaction starts.
204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/puppet/transaction.rb', line 204 def generate list = @catalog.vertices newlist = [] while ! list.empty? list.each do |resource| newlist += generate_additional_resources(resource, :generate) end list = newlist newlist = [] end end |
#generate_additional_resources(resource, method) ⇒ Object
A general method for recursively generating new resources from a resource.
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 |
# File 'lib/puppet/transaction.rb', line 174 def generate_additional_resources(resource, method) return [] unless resource.respond_to?(method) begin made = resource.send(method) rescue => detail puts detail.backtrace if Puppet[:trace] resource.err "Failed to generate additional resources using '#{method}': #{detail}" end return [] unless made made = [made] unless made.is_a?(Array) made.uniq.find_all do |res| begin res.tag(*resource.) @catalog.add_resource(res) do |r| r.finish make_parent_child_relationship(resource, [r]) # Call 'generate' recursively generate_additional_resources(r, method) end true rescue Puppet::Resource::Catalog::DuplicateResourceError res.info "Duplicate generated resource; skipping" false end end end |
#handle_qualified_tags(qualified) ⇒ Object
306 307 308 309 310 311 |
# File 'lib/puppet/transaction.rb', line 306 def ( qualified ) # The default behavior of Puppet::Util::Tagging is # to split qualified tags into parts. That would cause # qualified tags to match too broadly here. return end |
#ignore_tags? ⇒ Boolean
Should we ignore tags?
217 218 219 |
# File 'lib/puppet/transaction.rb', line 217 def ! (@catalog.host_config? or Puppet[:name] == "puppet") end |
#make_parent_child_relationship(resource, children) ⇒ Object
Copy an important relationships from the parent to the newly-generated child resource.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/puppet/transaction.rb', line 62 def make_parent_child_relationship(resource, children) depthfirst = resource.depthfirst? children.each do |gen_child| if depthfirst edge = [gen_child, resource] else edge = [resource, gen_child] end relationship_graph.add_vertex(gen_child) unless relationship_graph.edge?(edge[1], edge[0]) relationship_graph.add_edge(*edge) else resource.debug "Skipping automatic relationship to #{gen_child}" end end end |
#missing_tags?(resource) ⇒ Boolean
Is this resource tagged appropriately?
314 315 316 317 318 319 |
# File 'lib/puppet/transaction.rb', line 314 def (resource) return false if return false if .empty? not resource.tagged?(*) end |
#prefetch ⇒ Object
Prefetch any providers that support it. We don’t support prefetching types, just providers.
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/puppet/transaction.rb', line 232 def prefetch prefetchers = {} @catalog.vertices.each do |resource| if provider = resource.provider and provider.class.respond_to?(:prefetch) prefetchers[provider.class] ||= {} prefetchers[provider.class][resource.name] = resource end end # Now call prefetch, passing in the resources so that the provider instances can be replaced. prefetchers.each do |provider, resources| Puppet.debug "Prefetching #{provider.name} resources for #{provider.resource_type.name}" begin provider.prefetch(resources) rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Could not prefetch #{provider.resource_type.name} provider '#{provider.name}': #{detail}" end end end |
#prepare ⇒ Object
Prepare to evaluate the resources in a transaction.
254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/puppet/transaction.rb', line 254 def prepare # Now add any dynamically generated resources generate # Then prefetch. It's important that we generate and then prefetch, # so that any generated resources also get prefetched. prefetch # This will throw an error if there are cycles in the graph. @sorted_resources = relationship_graph.topsort end |
#relationship_graph ⇒ Object
266 267 268 |
# File 'lib/puppet/transaction.rb', line 266 def relationship_graph catalog.relationship_graph end |
#resource_status(resource) ⇒ Object
274 275 276 |
# File 'lib/puppet/transaction.rb', line 274 def resource_status(resource) report.resource_statuses[resource.to_s] || add_resource_status(Puppet::Resource::Status.new(resource)) end |
#scheduled?(resource) ⇒ Boolean
Is the resource currently scheduled?
279 280 281 |
# File 'lib/puppet/transaction.rb', line 279 def scheduled?(resource) self.ignoreschedules or resource_harness.scheduled?(resource_status(resource), resource) end |
#skip?(resource) ⇒ Boolean
Should this resource be skipped?
284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/puppet/transaction.rb', line 284 def skip?(resource) if (resource) resource.debug "Not tagged with #{tags.join(", ")}" elsif ! scheduled?(resource) resource.debug "Not scheduled" elsif failed_dependencies?(resource) resource.warning "Skipping because of failed dependencies" elsif resource.virtual? resource.debug "Skipping because virtual" else return false end true end |
#stop_processing? ⇒ Boolean
Wraps application run state check to flag need to interrupt processing
30 31 32 |
# File 'lib/puppet/transaction.rb', line 30 def stop_processing? Puppet::Application.stop_requested? end |
#tags ⇒ Object
The tags we should be checking.
300 301 302 303 304 |
# File 'lib/puppet/transaction.rb', line 300 def self. = Puppet[:tags] unless defined?() super end |