Class: Puppet::Transaction Private
- Includes:
- Util, Util::Tagging
- Defined in:
- lib/puppet/transaction.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
the class that actually walks our resource/property tree, collects the changes, and performs them
Defined Under Namespace
Classes: AdditionalResourceGenerator, Event, EventManager, Persistence, Report, ResourceHarness
Constant Summary
Constants included from Util::Tagging
Constants included from Util
Util::ALNUM, Util::ALPHA, Util::AbsolutePathPosix, Util::AbsolutePathWindows, Util::DEFAULT_POSIX_MODE, Util::DEFAULT_WINDOWS_MODE, Util::ESCAPED, Util::HEX, Util::HttpProxy, Util::PUPPET_STACK_INSERTION_FRAME, Util::RESERVED, Util::RFC_3986_URI_REGEX, Util::UNRESERVED, Util::UNSAFE
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
- #catalog ⇒ Object private
-
#event_manager ⇒ Object
readonly
private
Routes and stores any events and subscriptions.
- #for_network_device ⇒ Object private
- #ignoreschedules ⇒ Object private
- #persistence ⇒ Object readonly private
- #prefetch_failed_providers ⇒ Object readonly private
- #prefetched_providers ⇒ Object readonly private
-
#report ⇒ Object
readonly
private
The report, once generated.
-
#resource_harness ⇒ Object
readonly
private
Handles most of the actual interacting with resources.
Instance Method Summary collapse
-
#any_failed? ⇒ Boolean
private
Are there any failed resources in this transaction?.
-
#changed? ⇒ Boolean
private
Find all of the changed resources.
-
#evaluate(&block) ⇒ Object
private
This method does all the actual work of running a transaction.
-
#initialize(catalog, report, prioritizer) ⇒ Transaction
constructor
private
A new instance of Transaction.
-
#missing_tags?(resource) ⇒ Boolean
private
Is this resource tagged appropriately?.
-
#perform_pre_run_checks ⇒ void
private
Invoke the pre_run_check hook in every resource in the catalog.
- #prefetch_if_necessary(resource) ⇒ Object private
- #relationship_graph ⇒ Object private
- #resource_status(resource) ⇒ Object private
-
#skip?(resource) ⇒ Boolean
private
Should this resource be skipped?.
- #skip_tags ⇒ Object private
-
#stop_processing? ⇒ Boolean
private
Wraps application run state check to flag need to interrupt processing.
-
#tags ⇒ Object
private
The tags we should be checking.
Methods included from Util::Tagging
#merge_into, #merge_tags_from, #raw_tagged?, #set_tags, #tag, #tag_if_valid, #tagged?, #tags=, #valid_tag?
Methods included from Util
absolute_path?, benchmark, chuser, clear_environment, create_erb, default_env, deterministic_rand, deterministic_rand_int, exit_on_fail, format_backtrace_array, format_puppetstack_frame, get_env, get_environment, logmethods, merge_environment, path_to_uri, pretty_backtrace, replace_file, resolve_stackframe, rfc2396_escape, safe_posix_fork, set_env, skip_external_facts, symbolizehash, thinmark, uri_encode, uri_query_encode, uri_to_path, uri_unescape, which, withenv, withumask
Methods included from Util::POSIX
#get_posix_field, #gid, groups_of, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid
Methods included from Util::SymbolicFileMode
#display_mode, #normalize_symbolic_mode, #symbolic_mode_to_int, #valid_symbolic_mode?
Constructor Details
#initialize(catalog, report, prioritizer) ⇒ Transaction
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Transaction.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/puppet/transaction.rb', line 43 def initialize(catalog, report, prioritizer) @catalog = catalog @persistence = Puppet::Transaction::Persistence.new @report = report || Puppet::Transaction::Report.new(catalog.version, catalog.environment) @prioritizer = prioritizer @report.add_times(:config_retrieval, @catalog.retrieval_duration || 0) @event_manager = Puppet::Transaction::EventManager.new(self) @resource_harness = Puppet::Transaction::ResourceHarness.new(self) @prefetched_providers = Hash.new { |h, k| h[k] = {} } @prefetch_failed_providers = Hash.new { |h, k| h[k] = {} } # With merge_dependency_warnings, notify and warn about class dependency failures ... just once per class. TJK 2019-09-09 @merge_dependency_warnings = Puppet[:merge_dependency_warnings] @failed_dependencies_already_notified = Set.new() @failed_class_dependencies_already_notified = Set.new() @failed_class_dependencies_already_warned = Set.new() end |
Instance Attribute Details
#catalog ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
22 23 24 |
# File 'lib/puppet/transaction.rb', line 22 def catalog @catalog end |
#event_manager ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Routes and stores any events and subscriptions.
28 29 30 |
# File 'lib/puppet/transaction.rb', line 28 def event_manager @event_manager end |
#for_network_device ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
22 23 24 |
# File 'lib/puppet/transaction.rb', line 22 def for_network_device @for_network_device end |
#ignoreschedules ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
22 23 24 |
# File 'lib/puppet/transaction.rb', line 22 def ignoreschedules @ignoreschedules end |
#persistence ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
38 39 40 |
# File 'lib/puppet/transaction.rb', line 38 def persistence @persistence end |
#prefetch_failed_providers ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 |
# File 'lib/puppet/transaction.rb', line 33 def prefetch_failed_providers @prefetch_failed_providers end |
#prefetched_providers ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 |
# File 'lib/puppet/transaction.rb', line 33 def prefetched_providers @prefetched_providers end |
#report ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The report, once generated.
25 26 27 |
# File 'lib/puppet/transaction.rb', line 25 def report @report end |
#resource_harness ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Handles most of the actual interacting with resources
31 32 33 |
# File 'lib/puppet/transaction.rb', line 31 def resource_harness @resource_harness end |
Instance Method Details
#any_failed? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Are there any failed resources in this transaction?
213 214 215 216 217 |
# File 'lib/puppet/transaction.rb', line 213 def any_failed? report.resource_statuses.values.detect { |status| status.failed? || status.failed_to_restart? } end |
#changed? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Find all of the changed resources.
220 221 222 |
# File 'lib/puppet/transaction.rb', line 220 def changed? report.resource_statuses.values.find_all(&:changed).collect { |status| catalog.resource(status.resource) } end |
#evaluate(&block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
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.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 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 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 |
# File 'lib/puppet/transaction.rb', line 97 def evaluate(&block) block ||= method(:eval_resource) generator = AdditionalResourceGenerator.new(@catalog, nil, @prioritizer) @catalog.vertices.each { |resource| generator.generate_additional_resources(resource) } perform_pre_run_checks persistence.load if persistence.enabled?(catalog) Puppet.info _("Applying configuration version '%{version}'") % { version: catalog.version } if catalog.version continue_while = -> { !stop_processing? } post_evalable_providers = Set.new pre_process = lambda do |resource| prov_class = resource.provider.class post_evalable_providers << prov_class if prov_class.respond_to?(:post_resource_eval) prefetch_if_necessary(resource) # If we generated resources, we don't know what they are now # blocking, so we opt to recompute it, rather than try to track every # change that would affect the number. relationship_graph.clear_blockers if generator.eval_generate(resource) end providerless_types = [] overly_deferred_resource_handler = lambda do |resource| # We don't automatically assign unsuitable providers, so if there # is one, it must have been selected by the user. return if (resource) if resource.provider resource.err _("Provider %{name} is not functional on this host") % { name: resource.provider.class.name } else providerless_types << resource.type end resource_status(resource).failed = true end canceled_resource_handler = lambda do |resource| resource_status(resource).skipped = true resource.debug "Transaction canceled, skipping" end teardown = lambda do # Just once per type. No need to punish the user. providerless_types.uniq.each do |type| Puppet.err _("Could not find a suitable provider for %{type}") % { type: type } end post_evalable_providers.each do |provider| provider.post_resource_eval rescue => detail Puppet.log_exception(detail, _("post_resource_eval failed for provider %{provider}") % { provider: provider }) end persistence.save if persistence.enabled?(catalog) end # Graph cycles are returned as an array of arrays # - outer array is an array of cycles # - each inner array is an array of resources involved in a cycle # Short circuit resource evaluation if we detect cycle(s) in the graph. Mark # each corresponding resource as failed in the report before we fail to # ensure accurate reporting. graph_cycle_handler = lambda do |cycles| cycles.flatten.uniq.each do |resource| # We add a failed resource event to the status to ensure accurate # reporting through the event manager. resource_status(resource).fail_with_event(_('resource is part of a dependency cycle')) end raise Puppet::Error, _('One or more resource dependency cycles detected in graph') end # Generate the relationship graph, set up our generator to use it # for eval_generate, then kick off our traversal. generator.relationship_graph = relationship_graph progress = 0 relationship_graph.traverse(:while => continue_while, :pre_process => pre_process, :overly_deferred_resource_handler => overly_deferred_resource_handler, :canceled_resource_handler => canceled_resource_handler, :graph_cycle_handler => graph_cycle_handler, :teardown => teardown) do |resource| progress += 1 if resource.is_a?(Puppet::Type::Component) Puppet.warning _("Somehow left a component in the relationship graph") else if Puppet[:evaltrace] && @catalog.host_config? resource.info _("Starting to evaluate the resource (%{progress} of %{total})") % { progress: progress, total: relationship_graph.size } end seconds = thinmark { block.call(resource) } resource.info _("Evaluated in %{seconds} seconds") % { seconds: "%0.2f" % seconds } if Puppet[:evaltrace] && @catalog.host_config? end end # if one or more resources has attempted and failed to generate resources, # report it if generator.resources_failed_to_generate report.resources_failed_to_generate = true end # mark the end of transaction evaluate. report.transaction_completed = true Puppet.debug { "Finishing transaction #{object_id}" } end |
#missing_tags?(resource) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Is this resource tagged appropriately?
445 446 447 448 449 450 |
# File 'lib/puppet/transaction.rb', line 445 def (resource) return false if return false if .empty? !resource.tagged?(*) end |
#perform_pre_run_checks ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Invoke the pre_run_check hook in every resource in the catalog. This should (only) be called by Transaction#evaluate before applying the catalog.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/puppet/transaction.rb', line 77 def perform_pre_run_checks prerun_errors = {} @catalog.vertices.each do |res| res.pre_run_check rescue Puppet::Error => detail prerun_errors[res] = detail end unless prerun_errors.empty? prerun_errors.each do |res, detail| res.log_exception(detail) end raise Puppet::Error, _("Some pre-run checks failed") end end |
#prefetch_if_necessary(resource) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/puppet/transaction.rb', line 243 def prefetch_if_necessary(resource) provider_class = resource.provider.class if !provider_class.respond_to?(:prefetch) or prefetched_providers[resource.type][provider_class.name] or prefetch_failed_providers[resource.type][provider_class.name] return end 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
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
224 225 226 |
# File 'lib/puppet/transaction.rb', line 224 def relationship_graph catalog.relationship_graph(@prioritizer) end |
#resource_status(resource) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
228 229 230 |
# File 'lib/puppet/transaction.rb', line 228 def resource_status(resource) report.resource_statuses[resource.to_s] || add_resource_status(Puppet::Resource::Status.new(resource)) end |
#skip?(resource) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Should this resource be skipped?
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 |
# File 'lib/puppet/transaction.rb', line 401 def skip?(resource) if (resource) resource.debug "Skipping with skip tags #{.join(', ')}" elsif (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 # With merge_dependency_warnings, warn about class dependency failures ... just once per class. TJK 2019-09-09 unless resource.instance_of?(Puppet::Type.type(:whit)) if @merge_dependency_warnings && resource.parent && failed_dependencies?(resource.parent) ps = resource_status(resource.parent) ps.failed_dependencies.find_all { |d| !@failed_class_dependencies_already_warned.include?(d.ref) }.each do |dep| resource.parent.warning _("Skipping resources in class because of failed class dependencies") @failed_class_dependencies_already_warned.add(dep.ref) end else resource.warning _("Skipping because of failed dependencies") end end elsif resource_status(resource).failed? && @prefetch_failed_providers[resource.type][resource.provider.class.name] # Do not try to evaluate a resource with a known failed provider resource.warning _("Skipping because provider prefetch failed") elsif resource.virtual? resource.debug "Skipping because virtual" elsif !host_and_device_resource?(resource) && resource.appliable_to_host? && for_network_device resource.debug "Skipping host resources because running on a device" elsif !host_and_device_resource?(resource) && resource.appliable_to_device? && !for_network_device resource.debug "Skipping device resources because running on a posix host" else return false end true end |
#skip_tags ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
239 240 241 |
# File 'lib/puppet/transaction.rb', line 239 def @skip_tags ||= Puppet::Util::SkipTags.new(Puppet[:skip_tags]). end |
#stop_processing? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Wraps application run state check to flag need to interrupt processing
208 209 210 |
# File 'lib/puppet/transaction.rb', line 208 def stop_processing? Puppet::Application.stop_requested? && catalog.host_config? end |
#tags ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The tags we should be checking.
233 234 235 236 237 |
# File 'lib/puppet/transaction.rb', line 233 def self. = Puppet[:tags] unless defined?(@tags) super end |