Class: Puppet::Resource::Catalog::DiffCompiler

Inherits:
Indirector::Code
  • Object
show all
Includes:
Util
Defined in:
lib/puppet/indirector/catalog/diff_compiler.rb

Overview

This is almost the same as the Compiler indirection but it compiles two catalogs, one in a baseline environment (the one specified) by the regular way puppet determines the environment for a node, and once in a preview environment given as a request option.

Ideally, this would derive from the Compiler implementation, but it is too private and would require changes.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeDiffCompiler

Returns a new instance of DiffCompiler.



124
125
126
127
128
# File 'lib/puppet/indirector/catalog/diff_compiler.rb', line 124

def initialize
  Puppet::Util::Profiler.profile('Setup server facts for compiling', [:diff_compiler, :init_server_facts]) do
    set_server_facts
  end
end

Instance Attribute Details

#codeObject

Returns the value of attribute code.



20
21
22
# File 'lib/puppet/indirector/catalog/diff_compiler.rb', line 20

def code
  @code
end

Instance Method Details

#extract_facts_from_request(request) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/puppet/indirector/catalog/diff_compiler.rb', line 22

def extract_facts_from_request(request)
  return unless text_facts = request.options[:facts]
  unless format = request.options[:facts_format]
    raise ArgumentError, "Facts but no fact format provided for #{request.key}"
  end

  Puppet::Util::Profiler.profile('Found facts', [:compiler, :find_facts]) do
    # If the facts were encoded as yaml, then the param reconstitution system
    # in Network::HTTP::Handler will automagically deserialize the value.
    if text_facts.is_a?(Puppet::Node::Facts)
      facts = text_facts
    else
      # We unescape here because the corresponding code in Puppet::Configurer::FactHandler escapes
      facts = Puppet::Node::Facts.convert_from(format, CGI.unescape(text_facts))
    end

    unless facts.name == request.key
      raise Puppet::Error, "Catalog for #{request.key.inspect} was requested with fact definition for the wrong node (#{facts.name.inspect})."
    end

    options = {
      :environment => request.environment,
      :transaction_uuid => request.options[:transaction_uuid],
    }

    Puppet::Node::Facts.indirection.save(facts, nil, options)
  end
end

#filter(catalog) ⇒ Object

filter-out a catalog to remove exported resources



119
120
121
122
# File 'lib/puppet/indirector/catalog/diff_compiler.rb', line 119

def filter(catalog)
  return catalog.filter { |r| r.virtual? } if catalog.respond_to?(:filter)
  catalog
end

#find(request) ⇒ Object

The find request should

  • change logging to json output (as directed by baseline-log option)

  • compile in the baseline (reqular) environment given by the node/infrastructure

  • change logging to json output (as directed by preview-log option)

  • compile in the preview environment as directed by options

  • return a hash containing the baseline and preview catalogs

Compile a node’s catalog.



59
60
61
62
63
# File 'lib/puppet/indirector/catalog/diff_compiler.rb', line 59

def find(request)
  extract_facts_from_request(request)
  node = sanitize_node(node_from_request(request))
  compile(node, request.options)
end

#networked?Boolean

Is our compiler part of a network, or are we just local?

Returns:

  • (Boolean)


131
132
133
# File 'lib/puppet/indirector/catalog/diff_compiler.rb', line 131

def networked?
  Puppet.run_mode.master?
end

#sanitize_node(node) ⇒ Object

This method is copied from a Puppet::Parser::Compiler in Puppet 4.4.0



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/puppet/indirector/catalog/diff_compiler.rb', line 67

def sanitize_node(node)
  # Resurrect "trusted information" that comes from node/fact terminus.
  # The current way this is done in puppet db (currently the only one)
  # is to store the node parameter 'trusted' as a hash of the trusted information.
  #
  # Thus here there are two main cases:
  # 1. This terminus was used in a real agent call (only meaningful if someone curls the request as it would
  #  fail since the result is a hash of two catalogs).
  # 2  It is a command line call with a given node that use a terminus that:
  # 2.1 does not include a 'trusted' fact - use local from node trusted information
  # 2.2 has a 'trusted' fact - this in turn could be
  # 2.2.1 puppet db having stored trusted node data as a fact (not a great design)
  # 2.2.2 some other terminus having stored a fact called "trusted" (most likely that would have failed earlier, but could
  #       be spoofed).
  #
  # For the reasons above, the resurection of trusted node data with authenticated => true is only performed
  # if user is running as root, else it is resurrected as unauthenticated.
  #
  trusted_param = node.parameters['trusted']
  if trusted_param
    # Blows up if it is a parameter as it will be set as $trusted by the compiler as if it was a variable
    node.parameters.delete('trusted')
    unless trusted_param.is_a?(Hash) && %w{authenticated certname extensions}.all? {|key| trusted_param.has_key?(key) }
      # trusted is some kind of garbage, do not resurrect
      trusted_param = nil
    end
  else
    # trusted may be boolean false if set as a fact by someone
    trusted_param = nil
  end

  # The options for node.trusted_data in priority order are:
  # 1) node came with trusted_data so use that
  # 2) else if there is :trusted_information in the puppet context
  # 3) else if the node provided a 'trusted' parameter (parsed out above)
  # 4) last, fallback to local node trusted information
  #
  # Note that trusted_data should be a hash, but (2) and (4) are not
  # hashes, so we to_h at the end
  if !node.trusted_data
    trusted = Puppet.lookup(:trusted_information) do
      trusted_param || Puppet::Context::TrustedInformation.local(node)
    end

    # Ruby 1.9.3 can't apply to_h to a hash, so check first
    node.trusted_data = trusted.is_a?(Hash) ? trusted : trusted.to_h
  end

  node
end