puppet 0.16.0 → 0.18.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +98 -0
- data/Rakefile +5 -1
- data/bin/puppet +1 -1
- data/bin/puppetca +25 -11
- data/bin/puppetd +189 -66
- data/bin/puppetdoc +79 -62
- data/bin/puppetmasterd +93 -49
- data/bin/puppetrun +385 -0
- data/conf/redhat/client.init +5 -2
- data/conf/redhat/fileserver.conf +1 -1
- data/conf/redhat/lsb-config.patch +51 -0
- data/conf/redhat/puppet.spec +45 -18
- data/conf/redhat/puppetd.conf +32 -4
- data/conf/redhat/server.init +5 -2
- data/conf/solaris/pkginfo +7 -0
- data/conf/solaris/smf/puppetd.xml +77 -0
- data/conf/solaris/smf/puppetmasterd.xml +77 -0
- data/conf/solaris/smf/svc-puppetd +66 -0
- data/conf/solaris/smf/svc-puppetmasterd +62 -0
- data/examples/code/failers/noobjectrvalue +1 -0
- data/examples/code/snippets/deepclassheirarchy.pp +23 -0
- data/examples/code/snippets/defineoverrides.pp +17 -0
- data/examples/code/snippets/emptyexec.pp +3 -0
- data/examples/code/snippets/selectorvalues.pp +6 -1
- data/examples/code/snippets/tagged.pp +35 -0
- data/ext/ldap/puppet.schema +2 -2
- data/install.rb +4 -2
- data/lib/puppet.rb +206 -15
- data/lib/puppet/client.rb +30 -20
- data/lib/puppet/client/ca.rb +2 -2
- data/lib/puppet/client/dipper.rb +5 -9
- data/lib/puppet/client/master.rb +224 -44
- data/lib/puppet/client/pelement.rb +54 -9
- data/lib/puppet/client/proxy.rb +3 -2
- data/lib/puppet/client/reporter.rb +34 -0
- data/lib/puppet/client/runner.rb +17 -0
- data/lib/puppet/config.rb +136 -55
- data/lib/puppet/daemon.rb +59 -37
- data/lib/puppet/element.rb +2 -1
- data/lib/puppet/event.rb +14 -3
- data/lib/puppet/filetype.rb +28 -19
- data/lib/puppet/log.rb +297 -132
- data/lib/puppet/metric.rb +31 -131
- data/lib/puppet/networkclient.rb +73 -46
- data/lib/puppet/parameter.rb +49 -1
- data/lib/puppet/parsedfile.rb +32 -12
- data/lib/puppet/parser/ast.rb +6 -1
- data/lib/puppet/parser/ast/astarray.rb +32 -6
- data/lib/puppet/parser/ast/collection.rb +91 -0
- data/lib/puppet/parser/ast/compdef.rb +2 -2
- data/lib/puppet/parser/ast/component.rb +24 -11
- data/lib/puppet/parser/ast/function.rb +50 -0
- data/lib/puppet/parser/ast/hostclass.rb +70 -22
- data/lib/puppet/parser/ast/node.rb +17 -8
- data/lib/puppet/parser/ast/nodedef.rb +1 -1
- data/lib/puppet/parser/ast/objectdef.rb +28 -10
- data/lib/puppet/parser/ast/selector.rb +4 -1
- data/lib/puppet/parser/functions.rb +145 -0
- data/lib/puppet/parser/interpreter.rb +243 -86
- data/lib/puppet/parser/lexer.rb +5 -4
- data/lib/puppet/parser/parser.rb +586 -505
- data/lib/puppet/parser/scope.rb +337 -187
- data/lib/puppet/rails.rb +115 -0
- data/lib/puppet/rails/database.rb +40 -0
- data/lib/puppet/rails/host.rb +83 -0
- data/lib/puppet/rails/rails_object.rb +42 -0
- data/lib/puppet/rails/rails_parameter.rb +5 -0
- data/lib/puppet/reports/rrdgraph.rb +20 -0
- data/lib/puppet/reports/tagmail.rb +94 -0
- data/lib/puppet/server.rb +20 -4
- data/lib/puppet/server/authconfig.rb +14 -3
- data/lib/puppet/server/authstore.rb +2 -2
- data/lib/puppet/server/ca.rb +23 -11
- data/lib/puppet/server/filebucket.rb +10 -10
- data/lib/puppet/server/fileserver.rb +4 -8
- data/lib/puppet/server/master.rb +19 -22
- data/lib/puppet/server/pelement.rb +28 -16
- data/lib/puppet/server/report.rb +184 -0
- data/lib/puppet/server/runner.rb +62 -0
- data/lib/puppet/server/servlet.rb +23 -9
- data/lib/puppet/sslcertificates/ca.rb +25 -1
- data/lib/puppet/statechange.rb +34 -53
- data/lib/puppet/storage.rb +1 -2
- data/lib/puppet/transaction.rb +305 -133
- data/lib/puppet/transaction/report.rb +42 -0
- data/lib/puppet/transportable.rb +57 -33
- data/lib/puppet/type.rb +260 -127
- data/lib/puppet/type/component.rb +9 -21
- data/lib/puppet/type/cron.rb +367 -116
- data/lib/puppet/type/exec.rb +15 -16
- data/lib/puppet/type/group.rb +9 -1
- data/lib/puppet/type/nameservice.rb +2 -5
- data/lib/puppet/type/nameservice/netinfo.rb +3 -0
- data/lib/puppet/type/nameservice/objectadd.rb +23 -10
- data/lib/puppet/type/nameservice/pw.rb +16 -3
- data/lib/puppet/type/package.rb +25 -75
- data/lib/puppet/type/package/apple.rb +15 -1
- data/lib/puppet/type/package/apt.rb +37 -2
- data/lib/puppet/type/package/blastwave.rb +136 -0
- data/lib/puppet/type/package/dpkg.rb +4 -4
- data/lib/puppet/type/package/gem.rb +119 -0
- data/lib/puppet/type/package/openbsd.rb +7 -6
- data/lib/puppet/type/package/ports.rb +7 -2
- data/lib/puppet/type/package/rpm.rb +1 -1
- data/lib/puppet/type/package/sun.rb +23 -9
- data/lib/puppet/type/package/sunfreeware.rb +7 -0
- data/lib/puppet/type/package/yum.rb +16 -9
- data/lib/puppet/type/parsedtype.rb +7 -5
- data/lib/puppet/type/parsedtype/mount.rb +55 -34
- data/lib/puppet/type/parsedtype/port.rb +7 -1
- data/lib/puppet/type/parsedtype/sshkey.rb +6 -16
- data/lib/puppet/type/pfile.rb +115 -23
- data/lib/puppet/type/pfile/checksum.rb +18 -5
- data/lib/puppet/type/pfile/content.rb +2 -2
- data/lib/puppet/type/pfile/ensure.rb +3 -3
- data/lib/puppet/type/pfile/group.rb +2 -2
- data/lib/puppet/type/pfile/source.rb +28 -17
- data/lib/puppet/type/pfile/target.rb +25 -17
- data/lib/puppet/type/pfilebucket.rb +25 -6
- data/lib/puppet/type/schedule.rb +6 -6
- data/lib/puppet/type/service.rb +24 -14
- data/lib/puppet/type/service/debian.rb +1 -1
- data/lib/puppet/type/service/redhat.rb +13 -10
- data/lib/puppet/type/service/smf.rb +3 -3
- data/lib/puppet/type/state.rb +1 -2
- data/lib/puppet/type/symlink.rb +3 -4
- data/lib/puppet/type/user.rb +22 -10
- data/lib/puppet/type/yumrepo.rb +6 -1
- data/lib/puppet/type/zone.rb +595 -0
- data/lib/puppet/util.rb +58 -12
- data/test/client/client.rb +2 -2
- data/test/client/master.rb +92 -3
- data/test/client/pelement.rb +99 -0
- data/test/executables/puppetbin.rb +3 -4
- data/test/executables/puppetca.rb +3 -3
- data/test/executables/puppetd.rb +3 -3
- data/test/executables/puppetmasterd.rb +1 -5
- data/test/executables/puppetmodule.rb +2 -2
- data/test/language/ast.rb +200 -11
- data/test/language/functions.rb +245 -0
- data/test/language/interpreter.rb +155 -6
- data/test/language/lexer.rb +35 -2
- data/test/language/node.rb +48 -1
- data/test/language/parser.rb +250 -1
- data/test/language/rails.rb +105 -0
- data/test/language/scope.rb +304 -10
- data/test/language/snippets.rb +54 -5
- data/test/language/transportable.rb +60 -28
- data/test/other/config.rb +214 -1
- data/test/other/events.rb +67 -9
- data/test/other/log.rb +31 -5
- data/test/other/metrics.rb +23 -21
- data/test/other/parsedfile.rb +29 -2
- data/test/other/puppet.rb +79 -0
- data/test/other/report.rb +106 -0
- data/test/other/storage.rb +2 -2
- data/test/other/transactions.rb +128 -2
- data/test/puppet/utiltest.rb +10 -5
- data/test/puppettest.rb +193 -21
- data/test/server/authstore.rb +13 -4
- data/test/server/bucket.rb +33 -8
- data/test/server/ca.rb +44 -6
- data/test/server/master.rb +6 -7
- data/test/server/pelement.rb +15 -5
- data/test/server/report.rb +93 -0
- data/test/server/runner.rb +107 -0
- data/test/server/server.rb +28 -1
- data/test/types/cron.rb +339 -31
- data/test/types/file.rb +256 -24
- data/test/types/filebucket.rb +6 -2
- data/test/types/filesources.rb +41 -92
- data/test/types/group.rb +31 -1
- data/test/types/host.rb +2 -1
- data/test/types/mount.rb +18 -1
- data/test/types/package.rb +200 -18
- data/test/types/service.rb +5 -1
- data/test/types/sshkey.rb +2 -1
- data/test/types/symlink.rb +3 -2
- data/test/types/type.rb +180 -1
- data/test/types/user.rb +65 -27
- data/test/types/yumrepo.rb +15 -0
- data/test/types/zone.rb +437 -0
- metadata +43 -4
- data/bin/cf2puppet +0 -186
- data/conf/redhat/puppetmasterd.conf +0 -5
data/lib/puppet/parser/scope.rb
CHANGED
@@ -10,17 +10,77 @@ module Puppet::Parser
|
|
10
10
|
attr_accessor :file, :line, :type, :name
|
11
11
|
end
|
12
12
|
|
13
|
+
# A simple wrapper for templates, so they don't have full access to
|
14
|
+
# the scope objects.
|
15
|
+
class TemplateWrapper
|
16
|
+
attr_accessor :scope, :file
|
17
|
+
include Puppet::Util
|
18
|
+
Puppet::Util.logmethods(self)
|
19
|
+
|
20
|
+
def initialize(scope, file)
|
21
|
+
@scope = scope
|
22
|
+
if file =~ /^#{File::SEPARATOR}/
|
23
|
+
@file = file
|
24
|
+
else
|
25
|
+
@file = File.join(Puppet[:templatedir], file)
|
26
|
+
end
|
27
|
+
|
28
|
+
unless FileTest.exists?(@file)
|
29
|
+
raise Puppet::ParseError,
|
30
|
+
"Could not find template %s" % file
|
31
|
+
end
|
32
|
+
|
33
|
+
# We'll only ever not have an interpreter in testing, but, eh.
|
34
|
+
if @scope.interp
|
35
|
+
@scope.interp.newfile(@file)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(name, *args)
|
40
|
+
if value = @scope.lookupvar(name.to_s) and value != :undefined and value != ""
|
41
|
+
return value
|
42
|
+
else
|
43
|
+
# Just throw an error immediately, instead of searching for
|
44
|
+
# other missingmethod things or whatever.
|
45
|
+
raise Puppet::ParseError,
|
46
|
+
"Could not find value for '%s'" % name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def result
|
51
|
+
result = nil
|
52
|
+
benchmark(:info, "Interpolated template #{@file}") do
|
53
|
+
template = ERB.new(File.read(@file))
|
54
|
+
result = template.result(binding)
|
55
|
+
end
|
56
|
+
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
"template[%s]" % @file
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# This doesn't actually work right now.
|
66
|
+
Puppet.config.setdefaults(:puppet,
|
67
|
+
:lexical => [false, "Whether to use lexical scoping (vs. dynamic)."],
|
68
|
+
:templatedir => ["$vardir/templates",
|
69
|
+
"Where Puppet looks for template files."
|
70
|
+
]
|
71
|
+
)
|
72
|
+
|
13
73
|
Puppet::Util.logmethods(self)
|
14
74
|
|
15
75
|
include Enumerable
|
16
76
|
attr_accessor :parent, :level, :interp
|
17
77
|
attr_accessor :name, :type, :topscope, :base, :keyword
|
18
78
|
|
19
|
-
attr_accessor :top, :context
|
79
|
+
attr_accessor :top, :context, :translated, :collectable
|
20
80
|
|
21
81
|
# This is probably not all that good of an idea, but...
|
22
82
|
# This way a parent can share its tables with all of its children.
|
23
|
-
attr_writer :nodetable, :classtable, :definedtable
|
83
|
+
attr_writer :nodetable, :classtable, :definedtable, :exportable
|
24
84
|
|
25
85
|
# Whether we behave declaratively. Note that it's a class variable,
|
26
86
|
# so all scopes behave the same.
|
@@ -90,17 +150,23 @@ module Puppet::Parser
|
|
90
150
|
if typeklass and ! typeklass.isomorphic?
|
91
151
|
Puppet.info "Allowing duplicate %s" % type
|
92
152
|
else
|
153
|
+
exobj = @definedtable[type][name]
|
154
|
+
|
93
155
|
# Either it's a defined type, which are never
|
94
156
|
# isomorphic, or it's a non-isomorphic type.
|
95
157
|
msg = "Duplicate definition: %s[%s] is already defined" %
|
96
158
|
[type, name]
|
97
|
-
|
98
|
-
if
|
99
|
-
|
159
|
+
|
160
|
+
if exobj.file and exobj.line
|
161
|
+
msg << " in file %s at line %s" %
|
162
|
+
[exobj.file, exobj.line]
|
100
163
|
end
|
101
|
-
|
102
|
-
|
164
|
+
|
165
|
+
if hash[:line] or hash[:file]
|
166
|
+
msg << "; cannot redefine"
|
103
167
|
end
|
168
|
+
|
169
|
+
error = Puppet::ParseError.new(msg)
|
104
170
|
raise error
|
105
171
|
end
|
106
172
|
end
|
@@ -146,6 +212,12 @@ module Puppet::Parser
|
|
146
212
|
raise Puppet::DevError, "No classtable has been defined"
|
147
213
|
end
|
148
214
|
|
215
|
+
if defined? @exportable
|
216
|
+
scope.exportable = @exportable
|
217
|
+
else
|
218
|
+
raise Puppet::DevError, "No exportable has been defined"
|
219
|
+
end
|
220
|
+
|
149
221
|
if defined? @definedtable
|
150
222
|
scope.definedtable = @definedtable
|
151
223
|
else
|
@@ -174,12 +246,20 @@ module Puppet::Parser
|
|
174
246
|
unless defined? @classtable
|
175
247
|
raise Puppet::DevError, "Scope did not receive class table"
|
176
248
|
end
|
177
|
-
return @classtable.
|
249
|
+
return @classtable.collect { |id, klass|
|
250
|
+
# The class table can contain scopes or strings as its values
|
251
|
+
# so support them accordingly.
|
252
|
+
if klass.is_a? Scope
|
253
|
+
klass.type
|
254
|
+
else
|
255
|
+
klass
|
256
|
+
end
|
257
|
+
}
|
178
258
|
end
|
179
259
|
|
180
260
|
# Yield each child scope in turn
|
181
261
|
def each
|
182
|
-
@children.
|
262
|
+
@children.each { |child|
|
183
263
|
yield child
|
184
264
|
}
|
185
265
|
end
|
@@ -189,11 +269,9 @@ module Puppet::Parser
|
|
189
269
|
return unless classes
|
190
270
|
classes.each do |klass|
|
191
271
|
if code = lookuptype(klass)
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
:type => klass
|
196
|
-
)
|
272
|
+
# Just reuse the 'include' function, since that's the equivalent
|
273
|
+
# of what we're doing here.
|
274
|
+
function_include(klass)
|
197
275
|
end
|
198
276
|
end
|
199
277
|
end
|
@@ -201,7 +279,6 @@ module Puppet::Parser
|
|
201
279
|
# Evaluate a specific node's code. This method will normally be called
|
202
280
|
# on the top-level scope, but it actually evaluates the node at the
|
203
281
|
# appropriate scope.
|
204
|
-
#def evalnode(names, facts, classes = nil, parent = nil)
|
205
282
|
def evalnode(hash)
|
206
283
|
objects = hash[:ast]
|
207
284
|
names = hash[:names] or
|
@@ -210,12 +287,20 @@ module Puppet::Parser
|
|
210
287
|
classes = hash[:classes]
|
211
288
|
parent = hash[:parent]
|
212
289
|
|
290
|
+
# Always add "default" to our name list, so we're always searching
|
291
|
+
# for a default node.
|
292
|
+
names << "default"
|
293
|
+
|
213
294
|
scope = code = nil
|
214
295
|
# Find a node that matches one of our names
|
215
296
|
names.each { |node|
|
216
297
|
if nodehash = @nodetable[node]
|
217
298
|
code = nodehash[:node]
|
218
299
|
scope = nodehash[:scope]
|
300
|
+
|
301
|
+
if node == "default"
|
302
|
+
Puppet.info "Using default node"
|
303
|
+
end
|
219
304
|
break
|
220
305
|
end
|
221
306
|
}
|
@@ -240,17 +325,19 @@ module Puppet::Parser
|
|
240
325
|
scope.evalclasses(classes)
|
241
326
|
end
|
242
327
|
|
243
|
-
#
|
244
|
-
#
|
245
|
-
#
|
246
|
-
# a paltry amount of info from whomever's using the scope object.
|
328
|
+
# The top-level evaluate, used to evaluate a whole AST tree. This is
|
329
|
+
# a strange method, in that it turns around and calls evaluate() on its
|
330
|
+
# :ast argument.
|
247
331
|
def evaluate(hash)
|
248
332
|
objects = hash[:ast]
|
249
333
|
facts = hash[:facts] || {}
|
250
334
|
|
335
|
+
@@done = []
|
336
|
+
|
251
337
|
unless objects
|
252
338
|
raise Puppet::DevError, "Evaluation requires an AST tree"
|
253
339
|
end
|
340
|
+
|
254
341
|
# Set all of our facts in the top-level scope.
|
255
342
|
facts.each { |var, value|
|
256
343
|
self.setvar(var, value)
|
@@ -258,10 +345,11 @@ module Puppet::Parser
|
|
258
345
|
|
259
346
|
# Evaluate all of our configuration. This does not evaluate any
|
260
347
|
# node definitions.
|
261
|
-
objects.safeevaluate(:scope => self)
|
348
|
+
result = objects.safeevaluate(:scope => self)
|
262
349
|
|
263
|
-
# If they've provided a name or a parent, we assume they're looking
|
264
|
-
|
350
|
+
# If they've provided a name or a parent, we assume they're looking
|
351
|
+
# for nodes.
|
352
|
+
if hash[:searched]
|
265
353
|
# Specifying a parent node takes precedence, because it is assumed
|
266
354
|
# that this node was found in a remote repository like ldap.
|
267
355
|
gennode(hash)
|
@@ -277,15 +365,44 @@ module Puppet::Parser
|
|
277
365
|
# a cfengine module
|
278
366
|
end
|
279
367
|
|
280
|
-
|
281
|
-
objects.top = true
|
368
|
+
bucket = self.to_trans
|
282
369
|
|
283
370
|
# Add our class list
|
284
371
|
unless self.classlist.empty?
|
285
|
-
|
372
|
+
bucket.classes = self.classlist
|
373
|
+
end
|
374
|
+
|
375
|
+
# Now clean up after ourselves
|
376
|
+
[@@done].each do |table|
|
377
|
+
table.clear
|
286
378
|
end
|
287
379
|
|
288
|
-
return
|
380
|
+
return bucket
|
381
|
+
end
|
382
|
+
|
383
|
+
# Return the hash of objects that we specifically exported. We return
|
384
|
+
# a hash to make it easy for the caller to deduplicate based on name.
|
385
|
+
def exported(type)
|
386
|
+
if @exportable.include?(type)
|
387
|
+
return @exportable[type].dup
|
388
|
+
else
|
389
|
+
return {}
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
# Store our object in the central export table.
|
394
|
+
def exportobject(obj)
|
395
|
+
if @exportable.include?(obj.type) and
|
396
|
+
@exportable[obj.type].include?(obj.name)
|
397
|
+
raise Puppet::ParseError, "Object %s[%s] is already exported" %
|
398
|
+
[obj.type, obj.name]
|
399
|
+
end
|
400
|
+
|
401
|
+
debug "Exporting %s[%s]" % [obj.type, obj.name]
|
402
|
+
|
403
|
+
@exportable[obj.type][obj.name] = obj
|
404
|
+
|
405
|
+
return obj
|
289
406
|
end
|
290
407
|
|
291
408
|
# Pull in all of the appropriate classes and evaluate them. It'd
|
@@ -306,8 +423,8 @@ module Puppet::Parser
|
|
306
423
|
|
307
424
|
#Puppet.notice "hash is %s" %
|
308
425
|
# hash.inspect
|
309
|
-
Puppet.notice "Classes are %s, parent is %s" %
|
310
|
-
|
426
|
+
#Puppet.notice "Classes are %s, parent is %s" %
|
427
|
+
# [classes.inspect, parent.inspect]
|
311
428
|
|
312
429
|
if parent
|
313
430
|
arghash[:parentclass] = parent
|
@@ -325,52 +442,6 @@ module Puppet::Parser
|
|
325
442
|
scope.evalclasses(classes)
|
326
443
|
end
|
327
444
|
|
328
|
-
# Take all of our objects and evaluate them.
|
329
|
-
# def finish
|
330
|
-
# self.info "finishing"
|
331
|
-
# @objectlist.each { |object|
|
332
|
-
# if object.is_a? ScopeObj
|
333
|
-
# self.info "finishing %s" % object.name
|
334
|
-
# if obj = finishobject(object)
|
335
|
-
# @children << obj
|
336
|
-
# end
|
337
|
-
# end
|
338
|
-
# }
|
339
|
-
#
|
340
|
-
# @finished = true
|
341
|
-
#
|
342
|
-
# self.info "finished"
|
343
|
-
# end
|
344
|
-
#
|
345
|
-
# # If the object is defined in an upper scope, then add our
|
346
|
-
# # params to that upper scope; else, create a transobject
|
347
|
-
# # or evaluate the definition.
|
348
|
-
# def finishobject(object)
|
349
|
-
# type = object.type
|
350
|
-
# name = object.name
|
351
|
-
#
|
352
|
-
# # It should be a defined type.
|
353
|
-
# definedtype = lookuptype(type)
|
354
|
-
#
|
355
|
-
# unless definedtype
|
356
|
-
# error = Puppet::ParseError.new("No such type %s" % type)
|
357
|
-
# error.line = object.line
|
358
|
-
# error.file = object.file
|
359
|
-
# raise error
|
360
|
-
# end
|
361
|
-
#
|
362
|
-
# return definedtype.safeevaluate(
|
363
|
-
# :scope => self,
|
364
|
-
# :arguments => object,
|
365
|
-
# :type => type,
|
366
|
-
# :name => name
|
367
|
-
# )
|
368
|
-
# end
|
369
|
-
#
|
370
|
-
# def finished?
|
371
|
-
# @finished
|
372
|
-
# end
|
373
|
-
|
374
445
|
# Initialize our new scope. Defaults to having no parent and to
|
375
446
|
# being declarative.
|
376
447
|
def initialize(hash = {})
|
@@ -395,7 +466,10 @@ module Puppet::Parser
|
|
395
466
|
end
|
396
467
|
self.istop(hash[:declarative])
|
397
468
|
else
|
469
|
+
# This is here, rather than in newchild(), so that all
|
470
|
+
# of the later variable initialization works.
|
398
471
|
@parent.child = self
|
472
|
+
|
399
473
|
@level = @parent.level + 1
|
400
474
|
@interp = @parent.interp
|
401
475
|
@topscope = @parent.topscope
|
@@ -425,9 +499,6 @@ module Puppet::Parser
|
|
425
499
|
typehash[typekey] = Hash.new(nil)
|
426
500
|
}
|
427
501
|
|
428
|
-
# The list of simpler hash objects.
|
429
|
-
@objectlist = []
|
430
|
-
|
431
502
|
# This is just for collecting statements locally, so we can
|
432
503
|
# verify that there is no overlap within this specific scope
|
433
504
|
@localobjectable = Hash.new { |typehash,typekey|
|
@@ -463,6 +534,11 @@ module Puppet::Parser
|
|
463
534
|
# A table for storing nodes.
|
464
535
|
@nodetable = Hash.new(nil)
|
465
536
|
|
537
|
+
# The list of objects that will available for export.
|
538
|
+
@exportable = Hash.new { |types, type|
|
539
|
+
types[type] = {}
|
540
|
+
}
|
541
|
+
|
466
542
|
# Eventually, if we support sites, this will allow definitions
|
467
543
|
# of nodes with the same name in different sites. For now
|
468
544
|
# the top-level scope is always the only site scope.
|
@@ -517,6 +593,30 @@ module Puppet::Parser
|
|
517
593
|
return values
|
518
594
|
end
|
519
595
|
|
596
|
+
# Look up all of the exported objects of a given type. Just like
|
597
|
+
# lookupobject, this only searches up through parent classes, not
|
598
|
+
# the whole scope tree.
|
599
|
+
def lookupexported(type)
|
600
|
+
found = []
|
601
|
+
sub = proc { |table|
|
602
|
+
# We always return nil so that it will search all the way
|
603
|
+
# up the scope tree.
|
604
|
+
if table.has_key?(type)
|
605
|
+
table[type].each do |name, obj|
|
606
|
+
found << obj
|
607
|
+
end
|
608
|
+
nil
|
609
|
+
else
|
610
|
+
info table.keys.inspect
|
611
|
+
nil
|
612
|
+
end
|
613
|
+
}
|
614
|
+
|
615
|
+
value = lookup("object",sub, false)
|
616
|
+
|
617
|
+
return found
|
618
|
+
end
|
619
|
+
|
520
620
|
# Look up a node by name
|
521
621
|
def lookupnode(name)
|
522
622
|
#Puppet.debug "Looking up type %s" % name
|
@@ -567,19 +667,18 @@ module Puppet::Parser
|
|
567
667
|
|
568
668
|
# Look up a variable. The simplest value search we do.
|
569
669
|
def lookupvar(name)
|
570
|
-
#Puppet.debug "Looking up variable %s" % name
|
571
670
|
value = lookup("variable", name)
|
572
671
|
if value == :undefined
|
573
672
|
return ""
|
574
|
-
#error = Puppet::ParseError.new(
|
575
|
-
# "Undefined variable '%s'" % name
|
576
|
-
#)
|
577
|
-
#raise error
|
578
673
|
else
|
579
674
|
return value
|
580
675
|
end
|
581
676
|
end
|
582
677
|
|
678
|
+
def newcollection(coll)
|
679
|
+
@children << coll
|
680
|
+
end
|
681
|
+
|
583
682
|
# Add a new object to our object table.
|
584
683
|
def newobject(hash)
|
585
684
|
if @objectable[hash[:type]].include?(hash[:name])
|
@@ -591,25 +690,14 @@ module Puppet::Parser
|
|
591
690
|
|
592
691
|
obj = nil
|
593
692
|
|
594
|
-
|
595
|
-
# a ScopeObj, which will get replaced later.
|
596
|
-
if self.builtintype?(hash[:type])
|
597
|
-
obj = Puppet::TransObject.new(hash[:name], hash[:type])
|
693
|
+
obj = Puppet::TransObject.new(hash[:name], hash[:type])
|
598
694
|
|
599
|
-
|
600
|
-
else
|
601
|
-
obj = ScopeObj.new(nil)
|
602
|
-
obj.name = hash[:name]
|
603
|
-
obj.type = hash[:type]
|
604
|
-
end
|
695
|
+
@children << obj
|
605
696
|
|
606
697
|
@objectable[hash[:type]][hash[:name]] = obj
|
607
698
|
|
608
699
|
@definedtable[hash[:type]][hash[:name]] = obj
|
609
700
|
|
610
|
-
# Keep them in order, just for kicks
|
611
|
-
@objectlist << obj
|
612
|
-
|
613
701
|
return obj
|
614
702
|
end
|
615
703
|
|
@@ -631,15 +719,17 @@ module Puppet::Parser
|
|
631
719
|
# hash. We store the object ID, not class name, so that we
|
632
720
|
# can support multiple unrelated classes with the same name.
|
633
721
|
def setclass(id, name)
|
634
|
-
unless name =~ /^[a-z]\w*$/
|
722
|
+
unless name =~ /^[a-z][\w-]*$/
|
635
723
|
raise Puppet::ParseError, "Invalid class name '%s'" % name
|
636
724
|
end
|
637
725
|
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
726
|
+
@classtable[id] = name
|
727
|
+
end
|
728
|
+
|
729
|
+
# Store the scope for each class, so that other subclasses can look
|
730
|
+
# them up.
|
731
|
+
def setscope(id, scope)
|
732
|
+
@classtable[id] = scope
|
643
733
|
end
|
644
734
|
|
645
735
|
# Set defaults for a type. The typename should already be downcased,
|
@@ -687,6 +777,7 @@ module Puppet::Parser
|
|
687
777
|
# We have to store both the scope that's setting the node and
|
688
778
|
# the node itself, so that the node gets evaluated in the correct
|
689
779
|
# scope.
|
780
|
+
code.scope = self
|
690
781
|
@nodetable[name] = {
|
691
782
|
:scope => self,
|
692
783
|
:node => code
|
@@ -701,6 +792,7 @@ module Puppet::Parser
|
|
701
792
|
raise Puppet::ParseError,
|
702
793
|
"%s is already defined" % name
|
703
794
|
else
|
795
|
+
ltype.scope = self
|
704
796
|
@typetable[name] = ltype
|
705
797
|
end
|
706
798
|
end
|
@@ -722,6 +814,8 @@ module Puppet::Parser
|
|
722
814
|
file = hash[:file]
|
723
815
|
line = hash[:line]
|
724
816
|
|
817
|
+
collectable = hash[:collectable] || self.collectable
|
818
|
+
|
725
819
|
# Verify that we're not overriding any already-set parameters.
|
726
820
|
if localobj = @localobjectable[type][name]
|
727
821
|
params.each { |var, value|
|
@@ -737,48 +831,63 @@ module Puppet::Parser
|
|
737
831
|
}
|
738
832
|
end
|
739
833
|
|
740
|
-
|
741
|
-
|
742
|
-
objecttype.safeevaluate(
|
743
|
-
:name => name,
|
744
|
-
:type => type,
|
745
|
-
:arguments => params,
|
746
|
-
:scope => self
|
747
|
-
)
|
748
|
-
else
|
749
|
-
# First look for it in a parent scope
|
750
|
-
obj = lookupobject(:name => name, :type => type)
|
751
|
-
|
752
|
-
unless obj and obj != :undefined
|
753
|
-
unless obj = @objectable[type][name]
|
754
|
-
obj = self.newobject(
|
755
|
-
:type => type,
|
756
|
-
:name => name,
|
757
|
-
:line => line,
|
758
|
-
:file => file
|
759
|
-
)
|
834
|
+
# First look for it in a parent scope
|
835
|
+
obj = lookupobject(:name => name, :type => type)
|
760
836
|
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
837
|
+
if obj
|
838
|
+
unless collectable == obj.collectable
|
839
|
+
msg = nil
|
840
|
+
if collectable
|
841
|
+
msg = "Exported %s[%s] cannot override local objects"
|
842
|
+
[type, name]
|
843
|
+
else
|
844
|
+
msg = "Local %s[%s] cannot override exported objects"
|
845
|
+
[type, name]
|
768
846
|
end
|
847
|
+
|
848
|
+
error = Puppet::ParseError.new(msg)
|
849
|
+
error.line = line
|
850
|
+
error.file = file
|
851
|
+
raise error
|
769
852
|
end
|
853
|
+
end
|
770
854
|
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
855
|
+
unless obj and obj != :undefined
|
856
|
+
unless obj = @objectable[type][name]
|
857
|
+
obj = self.newobject(
|
858
|
+
:type => type,
|
859
|
+
:name => name,
|
860
|
+
:line => line,
|
861
|
+
:file => file
|
862
|
+
)
|
863
|
+
|
864
|
+
obj.collectable = collectable
|
865
|
+
|
866
|
+
# only set these if we've created the object,
|
867
|
+
# which is the most common case
|
868
|
+
# FIXME we eventually need to store the file
|
869
|
+
# and line with each param, not the object
|
870
|
+
# itself.
|
871
|
+
obj.file = file
|
872
|
+
obj.line = line
|
873
|
+
end
|
778
874
|
end
|
779
875
|
|
780
|
-
|
876
|
+
# Now add our parameters. This has the function of overriding
|
877
|
+
# existing values, which might have been defined in a higher
|
878
|
+
# scope.
|
879
|
+
params.each { |var,value|
|
880
|
+
# Add it to our found object
|
881
|
+
obj[var] = value
|
882
|
+
}
|
781
883
|
|
884
|
+
# This is only used for override verification -- the local object
|
885
|
+
# table does not have transobjects or whatever in it, it just has
|
886
|
+
# simple hashes. This is necessary because setobject can modify
|
887
|
+
# our object table or a parent class's object table, and we
|
888
|
+
# still need to make sure param settings cannot be duplicated
|
889
|
+
# within our scope.
|
890
|
+
@localobjectable[type][name] ||= {}
|
782
891
|
params.each { |var,value|
|
783
892
|
# And add it to the local table; mmm, hack
|
784
893
|
@localobjectable[type][name][var] = value
|
@@ -805,20 +914,16 @@ module Puppet::Parser
|
|
805
914
|
|
806
915
|
# Return an interpolated string.
|
807
916
|
def strinterp(string)
|
808
|
-
newstring = string.
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
newstring.sub!(regex,lookupvar(match[2]).to_s)
|
816
|
-
else
|
817
|
-
raise Puppet::DevError, "Could not match variable in %s" %
|
818
|
-
newstring
|
917
|
+
newstring = string.gsub(/\\\$|\$\{(\w+)\}|\$(\w+)/) do |value|
|
918
|
+
# If it matches the backslash, then just retun the dollar sign.
|
919
|
+
if value == '\\$'
|
920
|
+
'$'
|
921
|
+
else # look the variable up
|
922
|
+
var = $1 || $2
|
923
|
+
lookupvar($1 || $2)
|
819
924
|
end
|
820
925
|
end
|
821
|
-
|
926
|
+
|
822
927
|
return newstring.gsub(/\\t/, "\t").gsub(/\\n/, "\n").gsub(/\\s/, "\s")
|
823
928
|
end
|
824
929
|
|
@@ -845,6 +950,7 @@ module Puppet::Parser
|
|
845
950
|
tmp << @type.to_s
|
846
951
|
end
|
847
952
|
if @parent
|
953
|
+
#info "Looking for tags in %s" % @parent.type
|
848
954
|
@parent.tags.each { |tag|
|
849
955
|
if tag.nil? or tag == ""
|
850
956
|
Puppet.debug "parent returned tag %s" % tag.inspect
|
@@ -867,33 +973,36 @@ module Puppet::Parser
|
|
867
973
|
end
|
868
974
|
end
|
869
975
|
|
870
|
-
# Convert our scope to a
|
976
|
+
# Convert our scope to a TransBucket. Everything in our @localobjecttable
|
977
|
+
# gets converted to either an evaluated definition, or a TransObject
|
871
978
|
def to_trans
|
872
|
-
|
873
979
|
results = []
|
874
|
-
|
875
|
-
#
|
876
|
-
@
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
980
|
+
|
981
|
+
# Set this on entry, just in case someone tries to get all weird
|
982
|
+
@translated = true
|
983
|
+
|
984
|
+
@children.dup.each do |child|
|
985
|
+
if @@done.include?(child)
|
986
|
+
raise Puppet::DevError, "Already translated %s" %
|
987
|
+
child.object_id
|
988
|
+
else
|
989
|
+
@@done << child
|
990
|
+
end
|
991
|
+
#warning "Working on %s of type %s with id %s" %
|
992
|
+
# [child.type, child.class, child.object_id]
|
993
|
+
|
994
|
+
# If it's a scope, then it can only be a subclass's scope, so
|
995
|
+
# convert it to a transbucket and store it in our results list
|
996
|
+
result = nil
|
997
|
+
case child
|
998
|
+
when Scope
|
999
|
+
result = child.to_trans
|
1000
|
+
when Puppet::TransObject
|
1001
|
+
# These objects can map to defined types or builtin types.
|
1002
|
+
# Builtin types should be passed out as they are, but defined
|
1003
|
+
# types need to be evaluated. We have to wait until this
|
1004
|
+
# point so that subclass overrides can happen.
|
1005
|
+
|
897
1006
|
# Wait until the last minute to set tags, although this
|
898
1007
|
# probably should not matter
|
899
1008
|
child.tags = self.tags
|
@@ -905,16 +1014,57 @@ module Puppet::Parser
|
|
905
1014
|
# central table. This should maybe be in the evaluate
|
906
1015
|
# methods, but, eh.
|
907
1016
|
@topscope.addtags(child)
|
908
|
-
|
1017
|
+
|
1018
|
+
# Now that all that is done, check to see what kind of object
|
1019
|
+
# it is.
|
1020
|
+
if objecttype = lookuptype(child.type)
|
1021
|
+
# It's a defined type, so evaluate it. Retain whether
|
1022
|
+
# the object is collectable. If the object is collectable,
|
1023
|
+
# then it will store all of its contents into the
|
1024
|
+
# @exportable table, rather than returning them.
|
1025
|
+
result = objecttype.safeevaluate(
|
1026
|
+
:name => child.name,
|
1027
|
+
:type => child.type,
|
1028
|
+
:arguments => child.to_hash,
|
1029
|
+
:scope => self,
|
1030
|
+
:collectable => child.collectable
|
1031
|
+
)
|
1032
|
+
else
|
1033
|
+
# If it's collectable, then store it. It will be
|
1034
|
+
# stripped out in the interpreter using the collectstrip
|
1035
|
+
# method. If we don't do this, then these objects
|
1036
|
+
# don't get stored in the DB.
|
1037
|
+
if child.collectable
|
1038
|
+
exportobject(child)
|
1039
|
+
end
|
1040
|
+
result = child
|
1041
|
+
end
|
1042
|
+
# This is pretty hackish, but the collection has to actually
|
1043
|
+
# be performed after all of the classes and definitions are
|
1044
|
+
# evaluated, otherwise we won't catch objects that are exported
|
1045
|
+
# in them. I think this will still be pretty limited in some
|
1046
|
+
# cases, especially those where you are both exporting and
|
1047
|
+
# collecting, but it's the best I can do for now.
|
1048
|
+
when Puppet::Parser::AST::Collection
|
1049
|
+
child.perform(self).each do |obj|
|
1050
|
+
results << obj
|
1051
|
+
end
|
909
1052
|
else
|
910
1053
|
raise Puppet::DevError,
|
911
1054
|
"Puppet::Parse::Scope cannot handle objects of type %s" %
|
912
1055
|
child.class
|
913
1056
|
end
|
914
|
-
|
1057
|
+
|
1058
|
+
# Skip nil objects or empty transbuckets
|
1059
|
+
if result
|
1060
|
+
unless result.is_a? Puppet::TransBucket and result.empty?
|
1061
|
+
results << result
|
1062
|
+
end
|
1063
|
+
end
|
1064
|
+
end
|
915
1065
|
|
916
1066
|
# Get rid of any nil objects.
|
917
|
-
results
|
1067
|
+
results.reject! { |child|
|
918
1068
|
child.nil?
|
919
1069
|
}
|
920
1070
|
|
@@ -927,18 +1077,12 @@ module Puppet::Parser
|
|
927
1077
|
if defined? @name and @name
|
928
1078
|
bucket.name = @name
|
929
1079
|
end
|
930
|
-
|
931
1080
|
# it'd be nice not to have to do this...
|
932
1081
|
results.each { |result|
|
933
1082
|
#Puppet.warning "Result type is %s" % result.class
|
934
1083
|
bucket.push(result)
|
935
1084
|
}
|
936
|
-
|
937
|
-
bucket.type = @type
|
938
|
-
else
|
939
|
-
raise Puppet::ParseError,
|
940
|
-
"No type for scope %s" % @name
|
941
|
-
end
|
1085
|
+
bucket.type = @type
|
942
1086
|
|
943
1087
|
if defined? @keyword
|
944
1088
|
bucket.keyword = @keyword
|
@@ -961,11 +1105,18 @@ module Puppet::Parser
|
|
961
1105
|
# [bucket.name,self.object_id]
|
962
1106
|
return bucket
|
963
1107
|
else
|
964
|
-
Puppet.debug "
|
1108
|
+
Puppet.debug "typeless scope; just returning a list"
|
965
1109
|
return results
|
966
1110
|
end
|
967
1111
|
end
|
968
1112
|
|
1113
|
+
# Undefine a variable; only used for testing.
|
1114
|
+
def unsetvar(var)
|
1115
|
+
if @symtable.include?(var)
|
1116
|
+
@symtable.delete(var)
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
|
969
1120
|
protected
|
970
1121
|
|
971
1122
|
# This method abstracts recursive searching. It accepts the type
|
@@ -986,8 +1137,7 @@ module Puppet::Parser
|
|
986
1137
|
elsif table.include?(sub)
|
987
1138
|
return table[sub]
|
988
1139
|
elsif ! @parent.nil?
|
989
|
-
#
|
990
|
-
# [self.context, @parent.type, @parent.context]
|
1140
|
+
# Context is used for retricting overrides.
|
991
1141
|
if usecontext and self.context != @parent.context
|
992
1142
|
return :undefined
|
993
1143
|
else
|
@@ -1000,4 +1150,4 @@ module Puppet::Parser
|
|
1000
1150
|
end
|
1001
1151
|
end
|
1002
1152
|
|
1003
|
-
# $Id: scope.rb
|
1153
|
+
# $Id: scope.rb 1401 2006-07-18 14:00:33Z luke $
|