/
node.rb
147 lines (119 loc) · 3.9 KB
/
node.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
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
require 'puppet/indirector'
# A class for managing nodes, including their facts and environment.
class Puppet::Node
require 'puppet/node/facts'
require 'puppet/node/environment'
# Set up indirection, so that nodes can be looked for in
# the node sources.
extend Puppet::Indirector
# Adds the environment getter and setter, with some instance/string conversion
include Puppet::Node::Environment::Helper
# Use the node source as the indirection terminus.
indirects :node, :terminus_setting => :node_terminus, :doc => "Where to find node information.
A node is composed of its name, its facts, and its environment."
attr_accessor :name, :classes, :source, :ipaddress, :parameters
attr_reader :time, :facts
#
# Load json before trying to register.
Puppet.features.pson? and ::PSON.register_document_type('Node',self)
def self.from_pson(pson)
raise ArgumentError, "No name provided in pson data" unless name = pson['name']
node = new(name)
node.classes = pson['classes']
node.parameters = pson['parameters']
node.environment = pson['environment']
node
end
def to_pson(*args)
result = {
'document_type' => "Node",
'data' => {}
}
result['data']['name'] = name
result['data']['classes'] = classes unless classes.empty?
result['data']['parameters'] = parameters unless parameters.empty?
result['data']['environment'] = environment.name
result.to_pson(*args)
end
def environment
return super if @environment
if env = parameters["environment"]
self.environment = env
return super
end
# Else, return the default
Puppet::Node::Environment.new
end
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]
if env = options[:environment]
self.environment = env
end
@time = Time.now
end
# Merge the node facts with parameters from the node source.
def fact_merge
if @facts = Puppet::Node::Facts.indirection.find(name, :environment => environment)
merge(@facts.values)
end
rescue => detail
error = Puppet::Error.new("Could not retrieve facts for #{name}: #{detail}")
error.set_backtrace(detail.backtrace)
raise error
end
# Merge any random parameters into our parameter list.
def merge(params)
params.each do |name, value|
@parameters[name] = value unless @parameters.include?(name)
end
@parameters["environment"] ||= self.environment.name.to_s
end
# Calculate the list of names we might use for looking
# up our node. This is only used for AST nodes.
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}"
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
def split_name(name)
list = name.split(".")
tmp = []
list.each_with_index do |short, i|
tmp << list[0..i].join(".")
end
tmp.reverse
end
end