Class: Puppet::Node

Inherits:
Object show all
Extended by:
Indirector
Includes:
Util::PsychSupport
Defined in:
lib/puppet/node/environment.rb,
lib/puppet/node.rb

Overview

A class for managing nodes, including their facts and environment.

Defined Under Namespace

Classes: Environment, Exec, Facts, Memory, Msgpack, Plain, Rest, StoreConfigs, Yaml

Constant Summary collapse

ENVIRONMENT =
'environment'.freeze

Constants included from Indirector

Indirector::BadNameRegexp

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Indirector

configure_routes, indirects

Methods included from Util::PsychSupport

#encode_with, #init_with

Constructor Details

#initialize(name, options = {}) ⇒ Node

Returns a new instance of Node.

Raises:

  • (ArgumentError)


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
# File 'lib/puppet/node.rb', line 100

def initialize(name, options = {})
  raise ArgumentError, _("Node names cannot be nil") unless name
  @name = name

  if classes = options[:classes]
    if classes.is_a?(String)
      @classes = [classes]
    else
      @classes = classes
    end
  else
    @classes = []
  end

  @parameters = options[:parameters] || {}

  @facts = options[:facts]

  @server_facts = {}

  if env = options[:environment]
    self.environment = env
  end

  @time = Time.now
end

Instance Attribute Details

#classesObject

Returns the value of attribute classes.



19
20
21
# File 'lib/puppet/node.rb', line 19

def classes
  @classes
end

#environment_nameObject

Returns the value of attribute environment_name.



19
20
21
# File 'lib/puppet/node.rb', line 19

def environment_name
  @environment_name
end

#factsObject (readonly)

Returns the value of attribute facts.



20
21
22
# File 'lib/puppet/node.rb', line 20

def facts
  @facts
end

#ipaddressObject

Returns the value of attribute ipaddress.



19
20
21
# File 'lib/puppet/node.rb', line 19

def ipaddress
  @ipaddress
end

#nameObject

Returns the value of attribute name.



19
20
21
# File 'lib/puppet/node.rb', line 19

def name
  @name
end

#parametersObject

Returns the value of attribute parameters.



19
20
21
# File 'lib/puppet/node.rb', line 19

def parameters
  @parameters
end

#server_factsObject (readonly)

Returns the value of attribute server_facts.



22
23
24
# File 'lib/puppet/node.rb', line 22

def server_facts
  @server_facts
end

#sourceObject

Returns the value of attribute source.



19
20
21
# File 'lib/puppet/node.rb', line 19

def source
  @source
end

#timeObject (readonly)

Returns the value of attribute time.



20
21
22
# File 'lib/puppet/node.rb', line 20

def time
  @time
end

#trusted_dataObject

Returns the value of attribute trusted_data.



19
20
21
# File 'lib/puppet/node.rb', line 19

def trusted_data
  @trusted_data
end

Class Method Details

.from_data_hash(data) ⇒ Object



37
38
39
40
41
# File 'lib/puppet/node.rb', line 37

def self.from_data_hash(data)
  node = new(name)
  node.initialize_from_hash(data)
  node
end

Instance Method Details

#add_extra_facts(extra_facts) ⇒ 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.

Add extra facts, such as facts given to lookup on the command line The extra facts will override existing ones.

Parameters:

  • extra_facts (Hash{String=>Object})

    the facts to tadd



166
167
168
169
170
# File 'lib/puppet/node.rb', line 166

def add_extra_facts(extra_facts)
  @facts.add_extra_values(extra_facts)
  @parameters.merge!(extra_facts)
  nil
end

#add_server_facts(facts) ⇒ Object



172
173
174
175
176
177
178
# File 'lib/puppet/node.rb', line 172

def add_server_facts(facts)
  # Append the current environment to the list of server facts
  @server_facts = facts.merge({ "environment" => self.environment.name.to_s})

  # Merge the server facts into the parameters for the node
  merge(facts)
end

#environmentObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/puppet/node.rb', line 60

def environment
  if @environment
    @environment
  else
    if env = parameters[ENVIRONMENT]
      self.environment = env
    elsif environment_name
      self.environment = environment_name
    else
      # This should not be :current_environment, this is the default
      # for a node when it has not specified its environment
      # it will be used to establish what the current environment is.
      #
      self.environment = Puppet.lookup(:environments).get!(Puppet[:environment])
    end

    @environment
  end
end

#environment=(env) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/puppet/node.rb', line 80

def environment=(env)
  if env.is_a?(String) or env.is_a?(Symbol)
    @environment = Puppet.lookup(:environments).get!(env)
  else
    @environment = env
  end

  # Keep environment_name attribute and parameter in sync if they have been set
  unless @environment.nil?
    # always set the environment parameter. It becomes top scope $environment for a manifest during catalog compilation.
    @parameters[ENVIRONMENT] = @environment.name.to_s
    self.environment_name = @environment.name if instance_variable_defined?(:@environment_name)
  end
  @environment
end

#fact_merge(facts = nil) ⇒ nil

Merge the node facts with parameters from the node source.

Parameters:

  • facts (optional, Puppet::Node::Facts) (defaults to: nil)

    facts to merge into node parameters. Will query Facts indirection if not supplied.

Returns:

  • (nil)

Raises:

  • (Puppet::Error)

    Raise on failure to retrieve facts if not supplied



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/puppet/node.rb', line 133

def fact_merge(facts = nil)
  begin
    @facts = facts.nil? ? Puppet::Node::Facts.indirection.find(name, :environment => environment) : facts
  rescue => detail
    error = Puppet::Error.new(_("Could not retrieve facts for %{name}: %{detail}") % { name: name, detail: detail }, detail)
    error.set_backtrace(detail.backtrace)
    raise error
  end

  if !@facts.nil?
    @facts.sanitize
    # facts should never modify the environment parameter
    orig_param_env = @parameters[ENVIRONMENT]
    merge(@facts.values)
    @parameters[ENVIRONMENT] = orig_param_env
  end
end

#has_environment_instance?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/puppet/node.rb', line 96

def has_environment_instance?
  !@environment.nil?
end

#initialize_from_hash(data) ⇒ Object



26
27
28
29
30
31
32
33
34
35
# File 'lib/puppet/node.rb', line 26

def initialize_from_hash(data)
  @name       = data['name']       || (raise ArgumentError, _("No name provided in serialized data"))
  @classes    = data['classes']    || []
  @parameters = data['parameters'] || {}
  env_name = data['environment'] || @parameters[ENVIRONMENT]
  unless env_name.nil?
    @parameters[ENVIRONMENT] = env_name
    @environment_name = env_name.intern
  end
end

#merge(params) ⇒ Object

Merge any random parameters into our parameter list.



152
153
154
155
156
157
158
159
160
# File 'lib/puppet/node.rb', line 152

def merge(params)
  params.each do |name, value|
    if @parameters.include?(name)
      Puppet::Util::Warnings.warnonce(_("The node parameter '%{param_name}' for node '%{node_name}' was already set to '%{value}'. It could not be set to '%{desired_value}'") % { param_name: name, node_name: @name, value: @parameters[name], desired_value: value })
    else
      @parameters[name] = value
    end
  end
end

#namesObject

Calculate the list of names we might use for looking up our node. This is only used for AST nodes.



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
208
209
210
211
212
# File 'lib/puppet/node.rb', line 182

def names
  return [name] if Puppet.settings[:strict_hostname_checking]

  names = []

  names += split_name(name) if name.include?(".")

  # First, get the fqdn
  unless fqdn = parameters["fqdn"]
    if parameters["hostname"] and parameters["domain"]
      fqdn = parameters["hostname"] + "." + parameters["domain"]
    else
      Puppet.warning _("Host is missing hostname and/or domain: %{name}") % { name: name }
    end
  end

  # Now that we (might) have the fqdn, add each piece to the name
  # list to search, in order of longest to shortest.
  names += split_name(fqdn) if fqdn

  # And make sure the node name is first, since that's the most
  # likely usage.
  #   The name is usually the Certificate CN, but it can be
  # set to the 'facter' hostname instead.
  if Puppet[:node_name] == 'cert'
    names.unshift name
  else
    names.unshift parameters["hostname"]
  end
  names.uniq
end

#sanitizeObject

Resurrects and sanitizes trusted information in the node by modifying it and setting the trusted_data in the node from parameters. This modifies the node



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/puppet/node.rb', line 234

def sanitize
  # 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 resurrection of trusted node data with authenticated => true is only performed
  # if user is running as root, else it is resurrected as unauthenticated.
  #
  trusted_param = @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
    @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 !trusted_data
    trusted = Puppet.lookup(:trusted_information) do
      trusted_param || Puppet::Context::TrustedInformation.local(self)
    end

    self.trusted_data = trusted.to_h
  end
end

#serializable_parametersObject



54
55
56
57
58
# File 'lib/puppet/node.rb', line 54

def serializable_parameters
  new_params = parameters.dup
  new_params.delete(ENVIRONMENT)
  new_params
end

#split_name(name) ⇒ Object



214
215
216
217
218
219
220
221
# File 'lib/puppet/node.rb', line 214

def split_name(name)
  list = name.split(".")
  tmp = []
  list.each_with_index do |short, i|
    tmp << list[0..i].join(".")
  end
  tmp.reverse
end

#to_data_hashObject



43
44
45
46
47
48
49
50
51
52
# File 'lib/puppet/node.rb', line 43

def to_data_hash
  result = {
    'name' => name,
    'environment' => environment.name.to_s,
  }
  result['classes'] = classes unless classes.empty?
  serialized_params = self.serializable_parameters
  result['parameters'] = serialized_params unless serialized_params.empty?
  result
end