Class: Puppet::Node

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

Overview

Just define it, so this class has fewer load dependencies.

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)

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

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

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

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

  @facts = options[:facts]

  @server_facts = {}

  env = options[:environment]
  if env
    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.


169
170
171
172
173
# File 'lib/puppet/node.rb', line 169

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

#add_server_facts(facts) ⇒ Object


175
176
177
178
179
180
181
# File 'lib/puppet/node.rb', line 175

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

def environment
  if @environment
    @environment
  else
    env = parameters[ENVIRONMENT]
    if env
      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


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

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.

Raises:

  • (Puppet::Error)

    Raise on failure to retrieve facts if not supplied


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

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


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

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.


155
156
157
158
159
160
161
162
163
# File 'lib/puppet/node.rb', line 155

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.


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
213
214
215
216
# File 'lib/puppet/node.rb', line 185

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

  names = []

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

  # First, get the fqdn
  fqdn = parameters["fqdn"]
  unless 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


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
281
282
283
284
# File 'lib/puppet/node.rb', line 238

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


218
219
220
221
222
223
224
225
# File 'lib/puppet/node.rb', line 218

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