Class: Puppet::Transaction
- Includes:
- Util, Util::Tagging
- Defined in:
- lib/vendor/puppet/transaction.rb
Defined Under Namespace
Classes: Event, EventManager, Relationship_graph_wrapper, Report, ResourceHarness
Constant Summary
Constants included from Util
Util::AbsolutePathPosix, Util::AbsolutePathWindows
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.
-
#for_network_device ⇒ Object
Returns the value of attribute for_network_device.
-
#ignoreschedules ⇒ Object
Returns the value of attribute ignoreschedules.
-
#prefetched_providers ⇒ Object
readonly
Returns the value of attribute prefetched_providers.
-
#report ⇒ Object
readonly
The report, once generated.
-
#resource_harness ⇒ Object
readonly
Handles most of the actual interacting with resources.
Instance Method Summary collapse
-
#add_conditional_directed_dependency(parent, child, label = nil) ⇒ Object
Copy an important relationships from the parent to the newly-generated child resource.
- #add_dynamically_generated_resources ⇒ Object
- #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?.
-
#applied_resources ⇒ Object
Find all of the applied resources (including failed attempts).
-
#apply(resource, ancestor = nil) ⇒ Object
Apply all changes for a resource.
-
#changed? ⇒ Boolean
Find all of the changed resources.
- #eval_generate(resource) ⇒ Object
-
#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_additional_resources(resource) ⇒ 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.
-
#missing_tags?(resource) ⇒ Boolean
Is this resource tagged appropriately?.
-
#prefetch(provider_class, resources) ⇒ Object
Prefetch any providers that support it, yo.
- #prefetch_if_necessary(resource) ⇒ Object
- #relationship_graph ⇒ Object
- #resource_status(resource) ⇒ Object
- #resources_by_provider(type_name, provider_name) ⇒ 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
absolute_path?, activerecord_version, benchmark, binread, chuser, classproxy, #execfail, #execpipe, execute, execute_posix, execute_windows, logmethods, memory, path_to_uri, proxy, replace_file, safe_posix_fork, symbolize, symbolizehash, symbolizehash!, synchronize_on, thinmark, #threadlock, uri_to_path, wait_for_output, 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
235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/vendor/puppet/transaction.rb', line 235 def initialize(catalog, report = nil) @catalog = catalog @report = report || Puppet::Transaction::Report.new("apply", catalog.version, Puppet[:environment]) @event_manager = Puppet::Transaction::EventManager.new(self) @resource_harness = Puppet::Transaction::ResourceHarness.new(self) @prefetched_providers = Hash.new { |h,k| h[k] = {} } end |
Instance Attribute Details
#catalog ⇒ Object
Returns the value of attribute catalog.
15 16 17 |
# File 'lib/vendor/puppet/transaction.rb', line 15 def catalog @catalog end |
#component ⇒ Object
Returns the value of attribute component.
15 16 17 |
# File 'lib/vendor/puppet/transaction.rb', line 15 def component @component end |
#configurator ⇒ Object
Returns the value of attribute configurator.
16 17 18 |
# File 'lib/vendor/puppet/transaction.rb', line 16 def configurator @configurator end |
#event_manager ⇒ Object (readonly)
Routes and stores any events and subscriptions.
22 23 24 |
# File 'lib/vendor/puppet/transaction.rb', line 22 def event_manager @event_manager end |
#for_network_device ⇒ Object
Returns the value of attribute for_network_device.
15 16 17 |
# File 'lib/vendor/puppet/transaction.rb', line 15 def for_network_device @for_network_device end |
#ignoreschedules ⇒ Object
Returns the value of attribute ignoreschedules.
15 16 17 |
# File 'lib/vendor/puppet/transaction.rb', line 15 def ignoreschedules @ignoreschedules end |
#prefetched_providers ⇒ Object (readonly)
Returns the value of attribute prefetched_providers.
277 278 279 |
# File 'lib/vendor/puppet/transaction.rb', line 277 def prefetched_providers @prefetched_providers end |
#report ⇒ Object (readonly)
The report, once generated.
19 20 21 |
# File 'lib/vendor/puppet/transaction.rb', line 19 def report @report end |
#resource_harness ⇒ Object (readonly)
Handles most of the actual interacting with resources
25 26 27 |
# File 'lib/vendor/puppet/transaction.rb', line 25 def resource_harness @resource_harness end |
Instance Method Details
#add_conditional_directed_dependency(parent, child, label = nil) ⇒ Object
Copy an important relationships from the parent to the newly-generated child resource.
68 69 70 71 72 73 74 75 76 |
# File 'lib/vendor/puppet/transaction.rb', line 68 def add_conditional_directed_dependency(parent, child, label=nil) relationship_graph.add_vertex(child) edge = parent.depthfirst? ? [child, parent] : [parent, child] if relationship_graph.edge?(*edge.reverse) parent.debug "Skipping automatic relationship to #{child}" else relationship_graph.add_edge(edge[0],edge[1],label) end end |
#add_dynamically_generated_resources ⇒ Object
224 225 226 |
# File 'lib/vendor/puppet/transaction.rb', line 224 def add_dynamically_generated_resources @catalog.vertices.each { |resource| generate_additional_resources(resource) } end |
#add_resource_status(status) ⇒ Object
432 433 434 |
# File 'lib/vendor/puppet/transaction.rb', line 432 def add_resource_status(status) report.add_resource_status status end |
#add_times(hash) ⇒ Object
Add some additional times for reporting
36 37 38 39 40 |
# File 'lib/vendor/puppet/transaction.rb', line 36 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?
43 44 45 |
# File 'lib/vendor/puppet/transaction.rb', line 43 def any_failed? report.resource_statuses.values.detect { |status| status.failed? } end |
#applied_resources ⇒ Object
Find all of the applied resources (including failed attempts).
62 63 64 |
# File 'lib/vendor/puppet/transaction.rb', line 62 def applied_resources report.resource_statuses.values.collect { |status| catalog.resource(status.resource) } end |
#apply(resource, ancestor = nil) ⇒ Object
Apply all changes for a resource
48 49 50 51 52 53 54 |
# File 'lib/vendor/puppet/transaction.rb', line 48 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.
57 58 59 |
# File 'lib/vendor/puppet/transaction.rb', line 57 def changed? report.resource_statuses.values.find_all { |status| status.changed }.collect { |status| catalog.resource(status.resource) } end |
#eval_generate(resource) ⇒ Object
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 |
# File 'lib/vendor/puppet/transaction.rb', line 148 def eval_generate(resource) return false unless resource.respond_to?(:eval_generate) raise Puppet::DevError,"Depthfirst resources are not supported by eval_generate" if resource.depthfirst? begin made = resource.eval_generate.uniq return false if made.empty? made = made.inject({}) {|a,v| a.merge(v.name => v) } rescue => detail puts detail.backtrace if Puppet[:trace] resource.err "Failed to generate additional resources using 'eval_generate: #{detail}" return false end made.values.each do |res| begin res.tag(*resource.) @catalog.add_resource(res) res.finish rescue Puppet::Resource::Catalog::DuplicateResourceError res.info "Duplicate generated resource; skipping" end end sentinel = Puppet::Type.type(:whit).new(:name => "completed_#{resource.title}", :catalog => resource.catalog) # The completed whit is now the thing that represents the resource is done relationship_graph.adjacent(resource,:direction => :out,:type => :edges).each { |e| # But children run as part of the resource, not after it next if made[e.target.name] add_conditional_directed_dependency(sentinel, e.target, e.label) relationship_graph.remove_edge! e } default_label = Puppet::Resource::Catalog::Default_label made.values.each do |res| # Depend on the nearest ancestor we generated, falling back to the # resource if we have none parent_name = res.ancestors.find { |a| made[a] and made[a] != res } parent = made[parent_name] || resource add_conditional_directed_dependency(parent, res) # This resource isn't 'completed' until each child has run add_conditional_directed_dependency(res, sentinel, default_label) end # This edge allows the resource's events to propagate, though it isn't # strictly necessary for ordering purposes add_conditional_directed_dependency(resource, sentinel, default_label) true end |
#eval_resource(resource, ancestor = nil) ⇒ Object
Evaluate a single resource.
79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/vendor/puppet/transaction.rb', line 79 def eval_resource(resource, ancestor = nil) if skip?(resource) resource_status(resource).skipped = true else resource_status(resource).scheduled = true apply(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.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/vendor/puppet/transaction.rb', line 94 def evaluate add_dynamically_generated_resources Puppet.info "Applying configuration version '#{catalog.version}'" if catalog.version relationship_graph.traverse do |resource| if resource.is_a?(Puppet::Type::Component) Puppet.warning "Somehow left a component in the relationship graph" else resource.info "Starting to evaluate the resource" if Puppet[:evaltrace] and @catalog.host_config? seconds = thinmark { eval_resource(resource) } resource.info "Evaluated in %0.2f seconds" % seconds if Puppet[:evaltrace] and @catalog.host_config? end end Puppet.debug "Finishing transaction #{object_id}" end |
#events ⇒ Object
112 113 114 |
# File 'lib/vendor/puppet/transaction.rb', line 112 def events event_manager.events end |
#failed?(resource) ⇒ Boolean
116 117 118 |
# File 'lib/vendor/puppet/transaction.rb', line 116 def failed?(resource) s = resource_status(resource) and s.failed? end |
#failed_dependencies?(resource) ⇒ Boolean
Does this resource have any failed dependencies?
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/vendor/puppet/transaction.rb', line 121 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 # When we introduced the :whit into the graph, to reduce the combinatorial # explosion of edges, we also ended up reporting failures for containers # like class and stage. This is undesirable; while just skipping the # output isn't perfect, it is RC-safe. --daniel 2011-06-07 suppress_report = (resource.class == Puppet::Type.type(:whit)) relationship_graph.dependencies(resource).each do |dep| next unless failed?(dep) found_failed = true # See above. --daniel 2011-06-06 unless suppress_report then resource.notice "Dependency #{dep} has failures: #{resource_status(dep).failed}" end end found_failed end |
#generate_additional_resources(resource) ⇒ Object
A general method for recursively generating new resources from a resource.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/vendor/puppet/transaction.rb', line 201 def generate_additional_resources(resource) return unless resource.respond_to?(:generate) begin made = resource.generate rescue => detail puts detail.backtrace if Puppet[:trace] resource.err "Failed to generate additional resources using 'generate': #{detail}" end return unless made made = [made] unless made.is_a?(Array) made.uniq.each do |res| begin res.tag(*resource.) @catalog.add_resource(res) res.finish add_conditional_directed_dependency(resource, res) generate_additional_resources(res) rescue Puppet::Resource::Catalog::DuplicateResourceError res.info "Duplicate generated resource; skipping" end end end |
#handle_qualified_tags(qualified) ⇒ Object
476 477 478 479 480 481 |
# File 'lib/vendor/puppet/transaction.rb', line 476 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?
229 230 231 |
# File 'lib/vendor/puppet/transaction.rb', line 229 def ! (@catalog.host_config? or Puppet[:name] == "puppet") end |
#missing_tags?(resource) ⇒ Boolean
Is this resource tagged appropriately?
484 485 486 487 488 489 |
# File 'lib/vendor/puppet/transaction.rb', line 484 def (resource) return false if return false if .empty? not resource.tagged?(*) end |
#prefetch(provider_class, resources) ⇒ Object
Prefetch any providers that support it, yo. We don’t support prefetching types, just providers.
281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/vendor/puppet/transaction.rb', line 281 def prefetch(provider_class, resources) type_name = provider_class.resource_type.name return if @prefetched_providers[type_name][provider_class.name] Puppet.debug "Prefetching #{provider_class.name} resources for #{type_name}" begin provider_class.prefetch(resources) rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Could not prefetch #{type_name} provider '#{provider_class.name}': #{detail}" end @prefetched_providers[type_name][provider_class.name] = true end |
#prefetch_if_necessary(resource) ⇒ Object
262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/vendor/puppet/transaction.rb', line 262 def prefetch_if_necessary(resource) provider_class = resource.provider.class return unless provider_class.respond_to?(:prefetch) and !prefetched_providers[resource.type][provider_class.name] resources = resources_by_provider(resource.type, provider_class.name) if provider_class == resource.class.defaultprovider providerless_resources = resources_by_provider(resource.type, nil) providerless_resources.values.each {|res| res.provider = provider_class.name} resources.merge! providerless_resources end prefetch(provider_class, resources) end |
#relationship_graph ⇒ Object
428 429 430 |
# File 'lib/vendor/puppet/transaction.rb', line 428 def relationship_graph @relationship_graph ||= Relationship_graph_wrapper.new(catalog.relationship_graph,self) end |
#resource_status(resource) ⇒ Object
436 437 438 |
# File 'lib/vendor/puppet/transaction.rb', line 436 def resource_status(resource) report.resource_statuses[resource.to_s] || add_resource_status(Puppet::Resource::Status.new(resource)) end |
#resources_by_provider(type_name, provider_name) ⇒ Object
247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/vendor/puppet/transaction.rb', line 247 def resources_by_provider(type_name, provider_name) unless @resources_by_provider @resources_by_provider = Hash.new { |h, k| h[k] = Hash.new { |h, k| h[k] = {} } } @catalog.vertices.each do |resource| if resource.class.attrclass(:provider) prov = resource.provider && resource.provider.class.name @resources_by_provider[resource.type][prov][resource.name] = resource end end end @resources_by_provider[type_name][provider_name] || {} end |
#scheduled?(resource) ⇒ Boolean
Is the resource currently scheduled?
441 442 443 |
# File 'lib/vendor/puppet/transaction.rb', line 441 def scheduled?(resource) self.ignoreschedules or resource_harness.scheduled?(resource_status(resource), resource) end |
#skip?(resource) ⇒ Boolean
Should this resource be skipped?
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 |
# File 'lib/vendor/puppet/transaction.rb', line 446 def skip?(resource) if (resource) resource.debug "Not tagged with #{.join(", ")}" elsif ! scheduled?(resource) resource.debug "Not scheduled" elsif failed_dependencies?(resource) # When we introduced the :whit into the graph, to reduce the combinatorial # explosion of edges, we also ended up reporting failures for containers # like class and stage. This is undesirable; while just skipping the # output isn't perfect, it is RC-safe. --daniel 2011-06-07 unless resource.class == Puppet::Type.type(:whit) then resource.warning "Skipping because of failed dependencies" end elsif resource.virtual? resource.debug "Skipping because virtual" elsif resource.appliable_to_device? ^ for_network_device resource.debug "Skipping #{resource.appliable_to_device? ? 'device' : 'host'} resources because running on a #{for_network_device ? 'device' : 'host'}" else return false end true end |
#stop_processing? ⇒ Boolean
Wraps application run state check to flag need to interrupt processing
31 32 33 |
# File 'lib/vendor/puppet/transaction.rb', line 31 def stop_processing? Puppet::Application.stop_requested? end |