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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
# Support for modules
class Puppet::Module
TEMPLATES = "templates"
FILES = "files"
MANIFESTS = "manifests"
# Return an array of paths by splitting the +modulepath+ config
# parameter. Only consider paths that are absolute and existing
# directories
def self.modulepath(environment = nil)
dirs = Puppet.settings.value(:modulepath, environment).split(":")
if ENV["PUPPETLIB"]
dirs = ENV["PUPPETLIB"].split(":") + dirs
else
end
dirs.select do |p|
p =~ /^#{File::SEPARATOR}/ && File::directory?(p)
end
end
# Return an array of paths by splitting the +templatedir+ config
# parameter.
def self.templatepath(environment = nil)
dirs = Puppet.settings.value(:templatedir, environment).split(":")
dirs.select do |p|
p =~ /^#{File::SEPARATOR}/ && File::directory?(p)
end
end
# Find and return the +module+ that +path+ belongs to. If +path+ is
# absolute, or if there is no module whose name is the first component
# of +path+, return +nil+
def self.find(modname, environment = nil)
if modname =~ %r/^#{File::SEPARATOR}/
return nil
end
modpath = modulepath(environment).collect { |path|
File::join(path, modname)
}.find { |f| File::directory?(f) }
return nil unless modpath
return self.new(modname, modpath)
end
# Return an array of the full path of every subdirectory in each
# directory in the modulepath.
def self.all(environment = nil)
modulepath(environment).map do |mp|
Dir.new(mp).map do |modfile|
modpath = File.join(mp, modfile)
unless modfile == '.' or modfile == '..' or !File.directory?(modpath)
modpath
else
nil
end
end
end.flatten.compact
end
# Instance methods
# Find the concrete file denoted by +file+. If +file+ is absolute,
# return it directly. Otherwise try to find it as a template in a
# module. If that fails, return it relative to the +templatedir+ config
# param.
# In all cases, an absolute path is returned, which does not
# necessarily refer to an existing file
def self.find_template(template, environment = nil)
if template =~ /^#{File::SEPARATOR}/
return template
end
template_paths = templatepath(environment)
if template_paths
# If we can find the template in :templatedir, we return that.
td_file = template_paths.collect { |path|
File::join(path, template)
}.find { |f| File.exists?(f) }
return td_file unless td_file == nil
end
td_file = find_template_for_module(template, environment)
# check in the default template dir, if there is one
if td_file.nil?
raise Puppet::Error, "No valid template directory found, please check templatedir settings" if template_paths.nil?
td_file = File::join(template_paths.first, template)
end
td_file
end
def self.find_template_for_module(template, environment = nil)
path, file = split_path(template)
# Because templates don't have an assumed template name, like manifests do,
# we treat templates with no name as being templates in the main template
# directory.
if not file.nil?
mod = find(path, environment)
if mod
return mod.template(file)
end
end
nil
end
# Return a list of manifests (as absolute filenames) that match +pat+
# with the current directory set to +cwd+. If the first component of
# +pat+ does not contain any wildcards and is an existing module, return
# a list of manifests in that module matching the rest of +pat+
# Otherwise, try to find manifests matching +pat+ relative to +cwd+
def self.find_manifests(start, options = {})
cwd = options[:cwd] || Dir.getwd
module_name, pattern = split_path(start)
if module_name and mod = find(module_name, options[:environment])
return mod.manifests(pattern)
else
abspat = File::expand_path(start, cwd)
files = Dir.glob(abspat).reject { |f| FileTest.directory?(f) }
if files.size == 0
files = Dir.glob(abspat + ".pp").reject { |f| FileTest.directory?(f) }
end
return files
end
end
# Split the path into the module and the rest of the path.
# This method can and often does return nil, so anyone calling
# it needs to handle that.
def self.split_path(path)
if path =~ %r/^#{File::SEPARATOR}/
return nil
end
modname, rest = path.split(File::SEPARATOR, 2)
return nil if modname.nil? || modname.empty?
return modname, rest
end
attr_reader :name, :path
def initialize(name, path)
@name = name
@path = path
end
def template(file)
return File::join(path, TEMPLATES, file)
end
def files
return File::join(path, FILES)
end
# Return the list of manifests matching the given glob pattern,
# defaulting to 'init.pp' for empty modules.
def manifests(rest)
rest ||= "init.pp"
p = File::join(path, MANIFESTS, rest)
files = Dir.glob(p).reject { |f| FileTest.directory?(f) }
if files.size == 0
files = Dir.glob(p + ".pp")
end
return files
end
private :initialize
private_class_method :find_template_for_module
end
|