puppet 0.13.6 → 0.16.0
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 +57 -0
- data/Rakefile +38 -410
- data/bin/puppet +14 -12
- data/bin/puppetca +1 -3
- data/bin/puppetd +25 -7
- data/bin/puppetdoc +161 -104
- data/bin/puppetmasterd +4 -4
- data/conf/epm.list +8 -0
- data/conf/redhat/client.init +6 -1
- data/conf/redhat/no-chuser-0.15.1.patch +38 -0
- data/conf/redhat/puppet.spec +20 -5
- data/conf/redhat/puppetd.conf +1 -1
- data/conf/redhat/puppetmasterd.conf +1 -1
- data/conf/redhat/server.init +2 -4
- data/examples/code/snippets/{casestatement → casestatement.pp} +12 -1
- data/examples/code/snippets/selectorvalues.pp +15 -0
- data/examples/code/snippets/singleselector.pp +22 -0
- data/examples/code/snippets/tag.pp +9 -0
- data/ext/module_puppet +1 -1
- data/install.rb +303 -303
- data/lib/puppet.rb +7 -9
- data/lib/puppet/client.rb +18 -5
- data/lib/puppet/client/dipper.rb +12 -10
- data/lib/puppet/client/master.rb +113 -41
- data/lib/puppet/client/pelement.rb +20 -0
- data/lib/puppet/config.rb +113 -6
- data/lib/puppet/element.rb +1 -3
- data/lib/puppet/event.rb +12 -23
- data/lib/puppet/filetype.rb +93 -5
- data/lib/puppet/inifile.rb +201 -0
- data/lib/puppet/log.rb +18 -6
- data/lib/puppet/parameter.rb +80 -29
- data/lib/puppet/parser/ast.rb +6 -4
- data/lib/puppet/parser/ast/caseopt.rb +13 -4
- data/lib/puppet/parser/ast/casestatement.rb +2 -2
- data/lib/puppet/parser/ast/component.rb +4 -14
- data/lib/puppet/parser/ast/hostclass.rb +1 -1
- data/lib/puppet/parser/ast/leaf.rb +12 -0
- data/lib/puppet/parser/ast/node.rb +4 -4
- data/lib/puppet/parser/ast/objectdef.rb +5 -51
- data/lib/puppet/parser/ast/selector.rb +2 -0
- data/lib/puppet/parser/ast/tag.rb +26 -0
- data/lib/puppet/parser/interpreter.rb +89 -74
- data/lib/puppet/parser/lexer.rb +4 -3
- data/lib/puppet/parser/parser.rb +440 -378
- data/lib/puppet/parser/scope.rb +844 -887
- data/lib/puppet/server.rb +12 -1
- data/lib/puppet/server/authconfig.rb +166 -0
- data/lib/puppet/server/authstore.rb +8 -6
- data/lib/puppet/server/ca.rb +23 -26
- data/lib/puppet/server/filebucket.rb +24 -23
- data/lib/puppet/server/fileserver.rb +116 -47
- data/lib/puppet/server/master.rb +58 -19
- data/lib/puppet/server/pelement.rb +176 -0
- data/lib/puppet/server/rights.rb +78 -0
- data/lib/puppet/server/servlet.rb +19 -6
- data/lib/puppet/sslcertificates.rb +4 -2
- data/lib/puppet/sslcertificates/ca.rb +66 -34
- data/lib/puppet/storage.rb +20 -26
- data/lib/puppet/transaction.rb +49 -92
- data/lib/puppet/type.rb +142 -35
- data/lib/puppet/type/cron.rb +29 -14
- data/lib/puppet/type/exec.rb +92 -35
- data/lib/puppet/type/group.rb +29 -11
- data/lib/puppet/type/nameservice.rb +50 -1
- data/lib/puppet/type/nameservice/netinfo.rb +68 -1
- data/lib/puppet/type/nameservice/objectadd.rb +1 -0
- data/lib/puppet/type/package.rb +150 -109
- data/lib/puppet/type/package/apple.rb +27 -0
- data/lib/puppet/type/package/apt.rb +1 -0
- data/lib/puppet/type/package/darwinport.rb +97 -0
- data/lib/puppet/type/package/dpkg.rb +10 -2
- data/lib/puppet/type/package/freebsd.rb +19 -0
- data/lib/puppet/type/package/{bsd.rb → openbsd.rb} +36 -7
- data/lib/puppet/type/package/ports.rb +98 -0
- data/lib/puppet/type/package/rpm.rb +43 -7
- data/lib/puppet/type/package/sun.rb +53 -36
- data/lib/puppet/type/package/yum.rb +5 -16
- data/lib/puppet/type/parsedtype.rb +41 -29
- data/lib/puppet/type/parsedtype/host.rb +13 -5
- data/lib/puppet/type/parsedtype/mount.rb +250 -0
- data/lib/puppet/type/parsedtype/port.rb +8 -6
- data/lib/puppet/type/pfile.rb +284 -30
- data/lib/puppet/type/pfile/checksum.rb +96 -68
- data/lib/puppet/type/pfile/content.rb +16 -13
- data/lib/puppet/type/pfile/ensure.rb +64 -126
- data/lib/puppet/type/pfile/group.rb +12 -5
- data/lib/puppet/type/pfile/mode.rb +16 -4
- data/lib/puppet/type/pfile/source.rb +47 -73
- data/lib/puppet/type/pfile/target.rb +81 -0
- data/lib/puppet/type/pfile/uid.rb +10 -3
- data/lib/puppet/type/pfilebucket.rb +12 -3
- data/lib/puppet/type/schedule.rb +5 -1
- data/lib/puppet/type/service.rb +138 -66
- data/lib/puppet/type/service/debian.rb +9 -3
- data/lib/puppet/type/service/init.rb +51 -56
- data/lib/puppet/type/service/smf.rb +16 -6
- data/lib/puppet/type/state.rb +71 -32
- data/lib/puppet/type/symlink.rb +12 -7
- data/lib/puppet/type/tidy.rb +5 -1
- data/lib/puppet/type/user.rb +116 -20
- data/lib/puppet/type/yumrepo.rb +314 -0
- data/lib/puppet/util.rb +84 -14
- data/test/client/client.rb +41 -18
- data/test/client/master.rb +50 -4
- data/test/executables/puppetbin.rb +31 -4
- data/test/executables/puppetca.rb +18 -2
- data/test/language/ast.rb +201 -31
- data/test/language/interpreter.rb +8 -2
- data/test/{parser → language}/lexer.rb +1 -1
- data/test/language/node.rb +84 -0
- data/test/{parser → language}/parser.rb +1 -1
- data/test/language/scope.rb +101 -2
- data/test/language/snippets.rb +23 -2
- data/test/other/config.rb +99 -1
- data/test/other/filetype.rb +95 -0
- data/test/other/inifile.rb +114 -0
- data/test/other/log.rb +3 -2
- data/test/other/transactions.rb +55 -10
- data/test/puppet/utiltest.rb +25 -1
- data/test/puppettest.rb +140 -46
- data/test/server/authconfig.rb +56 -0
- data/test/server/bucket.rb +32 -18
- data/test/server/fileserver.rb +75 -30
- data/test/server/master.rb +27 -4
- data/test/server/pelement.rb +298 -0
- data/test/server/rights.rb +41 -0
- data/test/server/server.rb +2 -2
- data/test/tagging/tagging.rb +100 -1
- data/test/types/basic.rb +3 -3
- data/test/types/cron.rb +24 -1
- data/test/types/exec.rb +99 -1
- data/test/types/file.rb +298 -2
- data/test/types/filebucket.rb +4 -15
- data/test/types/filesources.rb +43 -14
- data/test/types/group.rb +1 -13
- data/test/types/mount.rb +277 -0
- data/test/types/package.rb +164 -33
- data/test/types/parameter.rb +107 -0
- data/test/types/port.rb +2 -1
- data/test/types/service.rb +37 -2
- data/test/types/state.rb +92 -0
- data/test/types/symlink.rb +30 -2
- data/test/types/tidy.rb +2 -14
- data/test/types/type.rb +35 -1
- data/test/types/user.rb +110 -1
- data/test/types/yumrepo.rb +95 -0
- metadata +316 -290
- data/test/types/filetype.rb +0 -160
data/lib/puppet/parser/scope.rb
CHANGED
@@ -1,1046 +1,1003 @@
|
|
1
1
|
# The scope class, which handles storing and retrieving variables and types and
|
2
2
|
# such.
|
3
3
|
|
4
|
+
require 'puppet/parser/parser'
|
4
5
|
require 'puppet/transportable'
|
5
6
|
|
6
|
-
module Puppet
|
7
|
-
|
8
|
-
class
|
9
|
-
|
10
|
-
|
11
|
-
end
|
7
|
+
module Puppet::Parser
|
8
|
+
class Scope
|
9
|
+
class ScopeObj < Hash
|
10
|
+
attr_accessor :file, :line, :type, :name
|
11
|
+
end
|
12
12
|
|
13
|
-
|
13
|
+
Puppet::Util.logmethods(self)
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
include Enumerable
|
16
|
+
attr_accessor :parent, :level, :interp
|
17
|
+
attr_accessor :name, :type, :topscope, :base, :keyword
|
18
18
|
|
19
|
-
|
19
|
+
attr_accessor :top, :context
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
# This is probably not all that good of an idea, but...
|
22
|
+
# This way a parent can share its tables with all of its children.
|
23
|
+
attr_writer :nodetable, :classtable, :definedtable
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
# Whether we behave declaratively. Note that it's a class variable,
|
26
|
+
# so all scopes behave the same.
|
27
|
+
@@declarative = true
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
# Retrieve and set the declarative setting.
|
30
|
+
def self.declarative
|
31
|
+
return @@declarative
|
32
|
+
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
def self.declarative=(val)
|
35
|
+
@@declarative = val
|
36
|
+
end
|
37
|
+
|
38
|
+
# Add all of the defaults for a given object to that object.
|
39
|
+
def adddefaults(obj)
|
40
|
+
defaults = lookupdefaults(obj.type)
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
42
|
+
defaults.each do |var, value|
|
43
|
+
unless obj[var]
|
44
|
+
self.debug "Adding default %s for %s" %
|
45
|
+
[var, obj.type]
|
46
|
+
|
47
|
+
obj[var] = value
|
43
48
|
end
|
44
|
-
list = @tagtable[obj.type][obj.name]
|
45
|
-
|
46
|
-
obj.tags.each { |tag|
|
47
|
-
unless list.include?(tag)
|
48
|
-
if tag.nil? or tag == ""
|
49
|
-
Puppet.debug "Got tag %s from %s(%s)" %
|
50
|
-
[tag.inspect, obj.type, obj.name]
|
51
|
-
else
|
52
|
-
list << tag
|
53
|
-
end
|
54
|
-
end
|
55
|
-
}
|
56
49
|
end
|
50
|
+
end
|
57
51
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
return false
|
64
|
-
end
|
52
|
+
# Add a single object's tags to the global list of tags for
|
53
|
+
# that object.
|
54
|
+
def addtags(obj)
|
55
|
+
unless defined? @tagtable
|
56
|
+
raise Puppet::DevError, "Told to add tags, but no tag table"
|
65
57
|
end
|
58
|
+
list = @tagtable[obj.type][obj.name]
|
66
59
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
return true
|
73
|
-
end
|
74
|
-
if @definedtable[type].include?(name)
|
75
|
-
typeklass = Puppet::Type.type(type)
|
76
|
-
if typeklass and ! typeklass.isomorphic?
|
77
|
-
Puppet.info "Allowing duplicate %s" % type
|
60
|
+
obj.tags.each { |tag|
|
61
|
+
unless list.include?(tag)
|
62
|
+
if tag.nil? or tag == ""
|
63
|
+
Puppet.debug "Got tag %s from %s(%s)" %
|
64
|
+
[tag.inspect, obj.type, obj.name]
|
78
65
|
else
|
79
|
-
|
80
|
-
# isomorphic, or it's a non-isomorphic type.
|
81
|
-
msg = "Duplicate definition: %s[%s] is already defined" %
|
82
|
-
[type, name]
|
83
|
-
error = Puppet::ParseError.new(msg)
|
84
|
-
if hash[:line]
|
85
|
-
error.line = hash[:line]
|
86
|
-
end
|
87
|
-
if hash[:file]
|
88
|
-
error.file = hash[:file]
|
89
|
-
end
|
90
|
-
raise error
|
66
|
+
list << tag
|
91
67
|
end
|
92
68
|
end
|
69
|
+
}
|
70
|
+
end
|
93
71
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
def declarative
|
102
|
-
self.class.declarative
|
72
|
+
# Is the type a builtin type?
|
73
|
+
def builtintype?(type)
|
74
|
+
if typeklass = Puppet::Type.type(type)
|
75
|
+
return typeklass
|
76
|
+
else
|
77
|
+
return false
|
103
78
|
end
|
79
|
+
end
|
104
80
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
names.sort { |a, b|
|
112
|
-
a[0] <=> b[0]
|
113
|
-
}.each { |name, tags|
|
114
|
-
Puppet.info "%s(%s): '%s'" % [type, name, tags.join("' '")]
|
115
|
-
}
|
116
|
-
}
|
81
|
+
# Verify that the given object isn't defined elsewhere.
|
82
|
+
def chkobjectclosure(hash)
|
83
|
+
type = hash[:type]
|
84
|
+
name = hash[:name]
|
85
|
+
unless name
|
86
|
+
return true
|
117
87
|
end
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
if defined? @nodetable
|
124
|
-
scope.nodetable = @nodetable
|
125
|
-
else
|
126
|
-
raise Puppet::DevError, "No nodetable has been defined"
|
127
|
-
end
|
128
|
-
|
129
|
-
if defined? @classtable
|
130
|
-
scope.classtable = @classtable
|
88
|
+
if @definedtable[type].include?(name)
|
89
|
+
typeklass = Puppet::Type.type(type)
|
90
|
+
if typeklass and ! typeklass.isomorphic?
|
91
|
+
Puppet.info "Allowing duplicate %s" % type
|
131
92
|
else
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# Test whether a given scope is declarative. Even though it's
|
143
|
-
# a global value, the calling objects don't need to know that.
|
144
|
-
def declarative?
|
145
|
-
@@declarative
|
146
|
-
end
|
147
|
-
|
148
|
-
# Remove a specific child.
|
149
|
-
def delete(child)
|
150
|
-
@children.delete(child)
|
151
|
-
end
|
152
|
-
|
153
|
-
# Verify that no nodescopes are hanging around.
|
154
|
-
def nodeclean
|
155
|
-
@children.find_all { |child|
|
156
|
-
if child.is_a?(Scope)
|
157
|
-
child.nodescope?
|
158
|
-
else
|
159
|
-
false
|
93
|
+
# Either it's a defined type, which are never
|
94
|
+
# isomorphic, or it's a non-isomorphic type.
|
95
|
+
msg = "Duplicate definition: %s[%s] is already defined" %
|
96
|
+
[type, name]
|
97
|
+
error = Puppet::ParseError.new(msg)
|
98
|
+
if hash[:line]
|
99
|
+
error.line = hash[:line]
|
160
100
|
end
|
161
|
-
|
162
|
-
|
163
|
-
}
|
164
|
-
|
165
|
-
@children.each { |child|
|
166
|
-
if child.is_a?(Scope)
|
167
|
-
child.nodeclean
|
101
|
+
if hash[:file]
|
102
|
+
error.file = hash[:file]
|
168
103
|
end
|
169
|
-
|
104
|
+
raise error
|
105
|
+
end
|
170
106
|
end
|
171
107
|
|
172
|
-
|
173
|
-
|
174
|
-
def nodescope?
|
175
|
-
@nodescope
|
176
|
-
end
|
108
|
+
return true
|
109
|
+
end
|
177
110
|
|
178
|
-
|
179
|
-
|
180
|
-
|
111
|
+
def declarative=(val)
|
112
|
+
self.class.declarative = val
|
113
|
+
end
|
181
114
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
@classtable = Hash.new(nil)
|
115
|
+
def declarative
|
116
|
+
self.class.declarative
|
117
|
+
end
|
186
118
|
|
187
|
-
|
188
|
-
|
189
|
-
|
119
|
+
# Log the existing tags. At some point this should be in a better
|
120
|
+
# place, but eh.
|
121
|
+
def logtags
|
122
|
+
@tagtable.sort { |a, b|
|
123
|
+
a[0] <=> b[0]
|
124
|
+
}.each { |type, names|
|
125
|
+
names.sort { |a, b|
|
126
|
+
a[0] <=> b[0]
|
127
|
+
}.each { |name, tags|
|
128
|
+
Puppet.info "%s(%s): '%s'" % [type, name, tags.join("' '")]
|
190
129
|
}
|
191
|
-
|
130
|
+
}
|
131
|
+
end
|
192
132
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
end
|
133
|
+
# Create a new child scope.
|
134
|
+
def child=(scope)
|
135
|
+
@children.push(scope)
|
197
136
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
end
|
203
|
-
return @classtable.keys
|
137
|
+
if defined? @nodetable
|
138
|
+
scope.nodetable = @nodetable
|
139
|
+
else
|
140
|
+
raise Puppet::DevError, "No nodetable has been defined"
|
204
141
|
end
|
205
142
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
}
|
143
|
+
if defined? @classtable
|
144
|
+
scope.classtable = @classtable
|
145
|
+
else
|
146
|
+
raise Puppet::DevError, "No classtable has been defined"
|
211
147
|
end
|
212
148
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
def evalnode(hash)
|
218
|
-
names = hash[:name]
|
219
|
-
facts = hash[:facts]
|
220
|
-
classes = hash[:classes]
|
221
|
-
parent = hash[:parent]
|
222
|
-
# First make sure there aren't any other node scopes lying around
|
223
|
-
self.nodeclean
|
224
|
-
|
225
|
-
# If they've passed classes in, then just generate from there.
|
226
|
-
if classes
|
227
|
-
return self.gennode(
|
228
|
-
:names => names,
|
229
|
-
:facts => facts,
|
230
|
-
:classes => classes,
|
231
|
-
:parent => parent
|
232
|
-
)
|
233
|
-
end
|
234
|
-
|
235
|
-
scope = code = nil
|
236
|
-
# Find a node that matches one of our names
|
237
|
-
names.each { |node|
|
238
|
-
if hash = @nodetable[node]
|
239
|
-
code = hash[:node]
|
240
|
-
scope = hash[:scope]
|
241
|
-
break
|
242
|
-
end
|
243
|
-
}
|
244
|
-
|
245
|
-
# And fail if we don't find one.
|
246
|
-
unless scope and code
|
247
|
-
raise Puppet::Error, "Could not find configuration for %s" %
|
248
|
-
names.join(" or ")
|
249
|
-
end
|
250
|
-
|
251
|
-
# We need to do a little skullduggery here. We want a
|
252
|
-
# temporary scope, because we don't want this scope to
|
253
|
-
# show up permanently in the scope tree -- otherwise we could
|
254
|
-
# not evaluate the node multiple times. We could conceivably
|
255
|
-
# cache the results, but it's not worth it at this stage.
|
256
|
-
|
257
|
-
# Note that we evaluate the node code with its containing
|
258
|
-
# scope, not with the top scope. We also retrieve the created
|
259
|
-
# nodescope so that we can get any classes set within it
|
260
|
-
nodescope = code.safeevaluate(:scope => scope, :facts => facts)
|
261
|
-
|
262
|
-
# We don't need to worry about removing the Node code because
|
263
|
-
# it will be removed during translation.
|
264
|
-
|
265
|
-
# convert the whole thing
|
266
|
-
objects = self.to_trans
|
267
|
-
|
268
|
-
# Add any evaluated classes to our top-level object
|
269
|
-
unless nodescope.classlist.empty?
|
270
|
-
objects.classes = nodescope.classlist
|
271
|
-
end
|
272
|
-
|
273
|
-
if objects.is_a?(Puppet::TransBucket)
|
274
|
-
objects.top = true
|
275
|
-
end
|
276
|
-
# I should do something to add the node as an object with tags
|
277
|
-
# but that will possibly end up with far too many tags.
|
278
|
-
#self.logtags
|
279
|
-
return objects
|
149
|
+
if defined? @definedtable
|
150
|
+
scope.definedtable = @definedtable
|
151
|
+
else
|
152
|
+
raise Puppet::DevError, "No definedtable has been defined"
|
280
153
|
end
|
154
|
+
end
|
281
155
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
names = hash[:names]
|
288
|
-
facts = hash[:facts]
|
289
|
-
classes = hash[:classes]
|
290
|
-
parent = hash[:parent]
|
291
|
-
name = names.shift
|
292
|
-
arghash = {
|
293
|
-
:type => name,
|
294
|
-
:code => AST::ASTArray.new(:pin => "[]")
|
295
|
-
}
|
296
|
-
|
297
|
-
if parent
|
298
|
-
arghash[:parentclass] = parent
|
299
|
-
end
|
156
|
+
# Test whether a given scope is declarative. Even though it's
|
157
|
+
# a global value, the calling objects don't need to know that.
|
158
|
+
def declarative?
|
159
|
+
@@declarative
|
160
|
+
end
|
300
161
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
# Now evaluate it, which evaluates the parent but doesn't really
|
306
|
-
# do anything else but does return the nodescope
|
307
|
-
scope = node.safeevaluate(:scope => self)
|
308
|
-
|
309
|
-
# And now evaluate each set klass within the nodescope.
|
310
|
-
classes.each { |klass|
|
311
|
-
if code = scope.lookuptype(klass)
|
312
|
-
#code.safeevaluate(scope, {}, klass, klass)
|
313
|
-
code.safeevaluate(
|
314
|
-
:scope => scope,
|
315
|
-
:facts => {},
|
316
|
-
:type => klass
|
317
|
-
)
|
318
|
-
end
|
319
|
-
}
|
162
|
+
# Remove a specific child.
|
163
|
+
def delete(child)
|
164
|
+
@children.delete(child)
|
165
|
+
end
|
320
166
|
|
321
|
-
|
322
|
-
|
167
|
+
# Are we the top scope?
|
168
|
+
def topscope?
|
169
|
+
@level == 1
|
170
|
+
end
|
323
171
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
172
|
+
# Return a list of all of the defined classes.
|
173
|
+
def classlist
|
174
|
+
unless defined? @classtable
|
175
|
+
raise Puppet::DevError, "Scope did not receive class table"
|
328
176
|
end
|
177
|
+
return @classtable.values
|
178
|
+
end
|
329
179
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
raise Puppet::ParseError, "Host %s is already defined" % name
|
337
|
-
else
|
338
|
-
#Puppet.warning "Setting node %s at level %s" % [name, @level]
|
180
|
+
# Yield each child scope in turn
|
181
|
+
def each
|
182
|
+
@children.reject { |child|
|
183
|
+
yield child
|
184
|
+
}
|
185
|
+
end
|
339
186
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
187
|
+
# Evaluate a list of classes.
|
188
|
+
def evalclasses(classes)
|
189
|
+
return unless classes
|
190
|
+
classes.each do |klass|
|
191
|
+
if code = lookuptype(klass)
|
192
|
+
code.safeevaluate(
|
344
193
|
:scope => self,
|
345
|
-
:
|
346
|
-
|
194
|
+
:facts => {},
|
195
|
+
:type => klass
|
196
|
+
)
|
347
197
|
end
|
348
198
|
end
|
199
|
+
end
|
349
200
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
201
|
+
# Evaluate a specific node's code. This method will normally be called
|
202
|
+
# on the top-level scope, but it actually evaluates the node at the
|
203
|
+
# appropriate scope.
|
204
|
+
#def evalnode(names, facts, classes = nil, parent = nil)
|
205
|
+
def evalnode(hash)
|
206
|
+
objects = hash[:ast]
|
207
|
+
names = hash[:names] or
|
208
|
+
raise Puppet::DevError, "Node names must be provided to evalnode"
|
209
|
+
facts = hash[:facts]
|
210
|
+
classes = hash[:classes]
|
211
|
+
parent = hash[:parent]
|
212
|
+
|
213
|
+
scope = code = nil
|
214
|
+
# Find a node that matches one of our names
|
215
|
+
names.each { |node|
|
216
|
+
if nodehash = @nodetable[node]
|
217
|
+
code = nodehash[:node]
|
218
|
+
scope = nodehash[:scope]
|
219
|
+
break
|
220
|
+
end
|
221
|
+
}
|
222
|
+
|
223
|
+
# And fail if we don't find one.
|
224
|
+
unless scope and code
|
225
|
+
raise Puppet::Error, "Could not find configuration for %s" %
|
226
|
+
names.join(" or ")
|
227
|
+
end
|
228
|
+
|
229
|
+
# We need to do a little skullduggery here. We want a
|
230
|
+
# temporary scope, because we don't want this scope to
|
231
|
+
# show up permanently in the scope tree -- otherwise we could
|
232
|
+
# not evaluate the node multiple times. We could conceivably
|
233
|
+
# cache the results, but it's not worth it at this stage.
|
234
|
+
|
235
|
+
# Note that we evaluate the node code with its containing
|
236
|
+
# scope, not with the top scope. We also retrieve the created
|
237
|
+
# scope so that we can get any classes set within it
|
238
|
+
nodescope = code.safeevaluate(:scope => scope, :facts => facts)
|
239
|
+
|
240
|
+
scope.evalclasses(classes)
|
241
|
+
end
|
361
242
|
|
362
|
-
|
243
|
+
# Evaluate normally, with no node definitions. This is a bit of a
|
244
|
+
# silly method, in that it just calls evaluate on the passed-in
|
245
|
+
# objects, and then calls to_trans on itself. It just conceals
|
246
|
+
# a paltry amount of info from whomever's using the scope object.
|
247
|
+
def evaluate(hash)
|
248
|
+
objects = hash[:ast]
|
249
|
+
facts = hash[:facts] || {}
|
250
|
+
|
251
|
+
unless objects
|
252
|
+
raise Puppet::DevError, "Evaluation requires an AST tree"
|
253
|
+
end
|
254
|
+
# Set all of our facts in the top-level scope.
|
255
|
+
facts.each { |var, value|
|
256
|
+
self.setvar(var, value)
|
257
|
+
}
|
258
|
+
|
259
|
+
# Evaluate all of our configuration. This does not evaluate any
|
260
|
+
# node definitions.
|
261
|
+
objects.safeevaluate(:scope => self)
|
262
|
+
|
263
|
+
# If they've provided a name or a parent, we assume they're looking for nodes.
|
264
|
+
if hash.include? :parentnode
|
265
|
+
# Specifying a parent node takes precedence, because it is assumed
|
266
|
+
# that this node was found in a remote repository like ldap.
|
267
|
+
gennode(hash)
|
268
|
+
elsif hash.include? :names # else, look for it in the config
|
269
|
+
evalnode(hash)
|
270
|
+
else
|
271
|
+
# Else we're not using nodes at all, so just evaluate any passed-in
|
272
|
+
# classes.
|
273
|
+
classes = hash[:classes] || []
|
274
|
+
evalclasses(classes)
|
363
275
|
|
364
276
|
# These classes would be passed in manually, via something like
|
365
277
|
# a cfengine module
|
366
|
-
classes.each { |klass|
|
367
|
-
if code = self.lookuptype(klass)
|
368
|
-
code.safeevaluate(
|
369
|
-
:scope => self,
|
370
|
-
:facts => {},
|
371
|
-
:type => klass
|
372
|
-
)
|
373
|
-
end
|
374
|
-
}
|
375
|
-
|
376
|
-
objects = self.to_trans
|
377
|
-
objects.top = true
|
378
|
-
|
379
|
-
# Add our class list
|
380
|
-
unless self.classlist.empty?
|
381
|
-
objects.classes = self.classlist
|
382
|
-
end
|
383
|
-
|
384
|
-
return objects
|
385
278
|
end
|
386
279
|
|
387
|
-
|
388
|
-
|
389
|
-
self.info "finishing"
|
390
|
-
@objectlist.each { |object|
|
391
|
-
if object.is_a? ScopeObj
|
392
|
-
self.info "finishing %s" % object.name
|
393
|
-
if obj = finishobject(object)
|
394
|
-
@children << obj
|
395
|
-
end
|
396
|
-
end
|
397
|
-
}
|
398
|
-
|
399
|
-
@finished = true
|
400
|
-
|
401
|
-
self.info "finished"
|
402
|
-
end
|
403
|
-
|
404
|
-
# If the object is defined in an upper scope, then add our
|
405
|
-
# params to that upper scope; else, create a transobject
|
406
|
-
# or evaluate the definition.
|
407
|
-
def finishobject(object)
|
408
|
-
type = object.type
|
409
|
-
name = object.name
|
410
|
-
|
411
|
-
# It should be a defined type.
|
412
|
-
definedtype = self.lookuptype(type)
|
413
|
-
|
414
|
-
unless definedtype
|
415
|
-
error = Puppet::ParseError.new("No such type %s" % type)
|
416
|
-
error.line = object.line
|
417
|
-
error.file = object.file
|
418
|
-
raise error
|
419
|
-
end
|
420
|
-
|
421
|
-
return definedtype.safeevaluate(
|
422
|
-
:scope => self,
|
423
|
-
:arguments => object,
|
424
|
-
:type => type,
|
425
|
-
:name => name
|
426
|
-
)
|
427
|
-
end
|
280
|
+
objects = self.to_trans
|
281
|
+
objects.top = true
|
428
282
|
|
429
|
-
|
430
|
-
|
283
|
+
# Add our class list
|
284
|
+
unless self.classlist.empty?
|
285
|
+
objects.classes = self.classlist
|
431
286
|
end
|
432
287
|
|
433
|
-
|
434
|
-
|
435
|
-
def initialize(hash = {})
|
436
|
-
@parent = nil
|
437
|
-
@type = nil
|
438
|
-
@name = nil
|
439
|
-
@finished = false
|
440
|
-
hash.each { |name, val|
|
441
|
-
method = name.to_s + "="
|
442
|
-
if self.respond_to? method
|
443
|
-
self.send(method, val)
|
444
|
-
else
|
445
|
-
raise Puppet::DevError, "Invalid scope argument %s" % name
|
446
|
-
end
|
447
|
-
}
|
448
|
-
#@parent = hash[:parent]
|
449
|
-
@nodescope = false
|
288
|
+
return objects
|
289
|
+
end
|
450
290
|
|
451
|
-
|
291
|
+
# Pull in all of the appropriate classes and evaluate them. It'd
|
292
|
+
# be nice if this didn't know quite so much about how AST::Node
|
293
|
+
# operated internally. This is used when a list of classes is passed in,
|
294
|
+
# instead of a node definition, such as from the cfengine module.
|
295
|
+
def gennode(hash)
|
296
|
+
names = hash[:names] or
|
297
|
+
raise Puppet::DevError, "Node names must be provided to gennode"
|
298
|
+
facts = hash[:facts]
|
299
|
+
classes = hash[:classes]
|
300
|
+
parent = hash[:parentnode]
|
301
|
+
name = names.shift
|
302
|
+
arghash = {
|
303
|
+
:type => name,
|
304
|
+
:code => AST::ASTArray.new(:pin => "[]")
|
305
|
+
}
|
306
|
+
|
307
|
+
#Puppet.notice "hash is %s" %
|
308
|
+
# hash.inspect
|
309
|
+
Puppet.notice "Classes are %s, parent is %s" %
|
310
|
+
[classes.inspect, parent.inspect]
|
311
|
+
|
312
|
+
if parent
|
313
|
+
arghash[:parentclass] = parent
|
314
|
+
end
|
315
|
+
|
316
|
+
# Create the node
|
317
|
+
node = AST::Node.new(arghash)
|
318
|
+
node.keyword = "node"
|
319
|
+
|
320
|
+
# Now evaluate it, which evaluates the parent and nothing else
|
321
|
+
# but does return the nodescope.
|
322
|
+
scope = node.safeevaluate(:scope => self)
|
323
|
+
|
324
|
+
# Finally evaluate our list of classes in this new scope.
|
325
|
+
scope.evalclasses(classes)
|
326
|
+
end
|
452
327
|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
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
|
+
# Initialize our new scope. Defaults to having no parent and to
|
375
|
+
# being declarative.
|
376
|
+
def initialize(hash = {})
|
377
|
+
@parent = nil
|
378
|
+
@type = nil
|
379
|
+
@name = nil
|
380
|
+
@finished = false
|
381
|
+
hash.each { |name, val|
|
382
|
+
method = name.to_s + "="
|
383
|
+
if self.respond_to? method
|
384
|
+
self.send(method, val)
|
458
385
|
else
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
386
|
+
raise Puppet::DevError, "Invalid scope argument %s" % name
|
387
|
+
end
|
388
|
+
}
|
389
|
+
|
390
|
+
@tags = []
|
391
|
+
|
392
|
+
if @parent.nil?
|
393
|
+
unless hash.include?(:declarative)
|
394
|
+
hash[:declarative] = true
|
395
|
+
end
|
396
|
+
self.istop(hash[:declarative])
|
397
|
+
else
|
398
|
+
@parent.child = self
|
399
|
+
@level = @parent.level + 1
|
400
|
+
@interp = @parent.interp
|
401
|
+
@topscope = @parent.topscope
|
402
|
+
@context = @parent.context
|
403
|
+
end
|
404
|
+
|
405
|
+
# Our child scopes and objects
|
406
|
+
@children = []
|
407
|
+
|
408
|
+
# The symbol table for this scope
|
409
|
+
@symtable = Hash.new(nil)
|
410
|
+
|
411
|
+
# The type table for this scope
|
412
|
+
@typetable = Hash.new(nil)
|
413
|
+
|
414
|
+
# All of the defaults set for types. It's a hash of hashes,
|
415
|
+
# with the first key being the type, then the second key being
|
416
|
+
# the parameter.
|
417
|
+
@defaultstable = Hash.new { |dhash,type|
|
418
|
+
dhash[type] = Hash.new(nil)
|
419
|
+
}
|
420
|
+
|
421
|
+
# The object table is similar, but it is actually a hash of hashes
|
422
|
+
# where the innermost objects are TransObject instances.
|
423
|
+
@objectable = Hash.new { |typehash,typekey|
|
424
|
+
# See #newobject for how to create the actual objects
|
425
|
+
typehash[typekey] = Hash.new(nil)
|
426
|
+
}
|
427
|
+
|
428
|
+
# The list of simpler hash objects.
|
429
|
+
@objectlist = []
|
430
|
+
|
431
|
+
# This is just for collecting statements locally, so we can
|
432
|
+
# verify that there is no overlap within this specific scope
|
433
|
+
@localobjectable = Hash.new { |typehash,typekey|
|
434
|
+
typehash[typekey] = Hash.new(nil)
|
435
|
+
}
|
436
|
+
|
437
|
+
# Map the names to the tables.
|
438
|
+
@map = {
|
439
|
+
"variable" => @symtable,
|
440
|
+
"type" => @typetable,
|
441
|
+
"node" => @nodetable,
|
442
|
+
"object" => @objectable,
|
443
|
+
"defaults" => @defaultstable
|
444
|
+
}
|
445
|
+
end
|
465
446
|
|
466
|
-
|
467
|
-
|
447
|
+
# Mark that we're the top scope, and set some hard-coded info.
|
448
|
+
def istop(declarative = true)
|
449
|
+
# the level is mostly used for debugging
|
450
|
+
@level = 1
|
468
451
|
|
469
|
-
|
470
|
-
|
452
|
+
# The table for storing class singletons. This will only actually
|
453
|
+
# be used by top scopes and node scopes.
|
454
|
+
@classtable = Hash.new(nil)
|
471
455
|
|
472
|
-
|
473
|
-
@typetable = Hash.new(nil)
|
456
|
+
self.class.declarative = declarative
|
474
457
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
dhash[type] = Hash.new(nil)
|
480
|
-
}
|
458
|
+
# The table for all defined objects.
|
459
|
+
@definedtable = Hash.new { |types, type|
|
460
|
+
types[type] = {}
|
461
|
+
}
|
481
462
|
|
482
|
-
|
483
|
-
|
484
|
-
@objectable = Hash.new { |typehash,typekey|
|
485
|
-
# See #newobject for how to create the actual objects
|
486
|
-
typehash[typekey] = Hash.new(nil)
|
487
|
-
}
|
488
|
-
|
489
|
-
# The list of simpler hash objects.
|
490
|
-
@objectlist = []
|
463
|
+
# A table for storing nodes.
|
464
|
+
@nodetable = Hash.new(nil)
|
491
465
|
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
}
|
466
|
+
# Eventually, if we support sites, this will allow definitions
|
467
|
+
# of nodes with the same name in different sites. For now
|
468
|
+
# the top-level scope is always the only site scope.
|
469
|
+
@sitescope = true
|
497
470
|
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
"object" => @objectable,
|
504
|
-
"defaults" => @defaultstable
|
471
|
+
# And create a tag table, so we can collect all of the tags
|
472
|
+
# associated with any objects created in this scope tree
|
473
|
+
@tagtable = Hash.new { |types, type|
|
474
|
+
types[type] = Hash.new { |names, name|
|
475
|
+
names[name] = []
|
505
476
|
}
|
506
|
-
|
477
|
+
}
|
507
478
|
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
# The table for storing class singletons. This will only actually
|
514
|
-
# be used by top scopes and node scopes.
|
515
|
-
@classtable = Hash.new(nil)
|
479
|
+
@context = nil
|
480
|
+
@topscope = self
|
481
|
+
@type = "puppet"
|
482
|
+
@name = "top"
|
483
|
+
end
|
516
484
|
|
517
|
-
|
485
|
+
# Look up a given class. This enables us to make sure classes are
|
486
|
+
# singletons
|
487
|
+
def lookupclass(klassid)
|
488
|
+
unless defined? @classtable
|
489
|
+
raise Puppet::DevError, "Scope did not receive class table"
|
490
|
+
end
|
491
|
+
return @classtable[klassid]
|
492
|
+
end
|
518
493
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
494
|
+
# Collect all of the defaults set at any higher scopes.
|
495
|
+
# This is a different type of lookup because it's additive --
|
496
|
+
# it collects all of the defaults, with defaults in closer scopes
|
497
|
+
# overriding those in later scopes.
|
498
|
+
def lookupdefaults(type)
|
499
|
+
values = {}
|
500
|
+
|
501
|
+
# first collect the values from the parents
|
502
|
+
unless @parent.nil?
|
503
|
+
@parent.lookupdefaults(type).each { |var,value|
|
504
|
+
values[var] = value
|
523
505
|
}
|
506
|
+
end
|
524
507
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
# the top-level scope is always the only site scope.
|
531
|
-
@sitescope = true
|
532
|
-
|
533
|
-
# And create a tag table, so we can collect all of the tags
|
534
|
-
# associated with any objects created in this scope tree
|
535
|
-
@tagtable = Hash.new { |types, type|
|
536
|
-
types[type] = Hash.new { |names, name|
|
537
|
-
names[name] = []
|
538
|
-
}
|
508
|
+
# then override them with any current values
|
509
|
+
# this should probably be done differently
|
510
|
+
if @defaultstable.include?(type)
|
511
|
+
@defaultstable[type].each { |var,value|
|
512
|
+
values[var] = value
|
539
513
|
}
|
514
|
+
end
|
515
|
+
#Puppet.debug "Got defaults for %s: %s" %
|
516
|
+
# [type,values.inspect]
|
517
|
+
return values
|
518
|
+
end
|
540
519
|
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
520
|
+
# Look up a node by name
|
521
|
+
def lookupnode(name)
|
522
|
+
#Puppet.debug "Looking up type %s" % name
|
523
|
+
value = lookup("type",name)
|
524
|
+
if value == :undefined
|
525
|
+
return nil
|
526
|
+
else
|
527
|
+
#Puppet.debug "Found node %s" % name
|
528
|
+
return value
|
545
529
|
end
|
530
|
+
end
|
546
531
|
|
547
|
-
|
548
|
-
|
549
|
-
#
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
end
|
532
|
+
# Look up a defined type.
|
533
|
+
def lookuptype(name)
|
534
|
+
#Puppet.debug "Looking up type %s" % name
|
535
|
+
value = lookup("type",name)
|
536
|
+
if value == :undefined
|
537
|
+
return nil
|
538
|
+
else
|
539
|
+
#Puppet.debug "Found type %s" % name
|
540
|
+
return value
|
541
|
+
end
|
542
|
+
end
|
559
543
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
544
|
+
# Look up an object by name and type. This should only look up objects
|
545
|
+
# within a class structure, not within the entire scope structure.
|
546
|
+
def lookupobject(hash)
|
547
|
+
type = hash[:type]
|
548
|
+
name = hash[:name]
|
549
|
+
#Puppet.debug "Looking up object %s of type %s in level %s" %
|
550
|
+
# [name, type, @level]
|
551
|
+
sub = proc { |table|
|
552
|
+
if table.include?(type)
|
553
|
+
if table[type].include?(name)
|
554
|
+
table[type][name]
|
571
555
|
end
|
572
556
|
else
|
573
|
-
|
557
|
+
nil
|
574
558
|
end
|
559
|
+
}
|
560
|
+
value = lookup("object",sub, true)
|
561
|
+
if value == :undefined
|
562
|
+
return nil
|
563
|
+
else
|
564
|
+
return value
|
575
565
|
end
|
566
|
+
end
|
576
567
|
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
568
|
+
# Look up a variable. The simplest value search we do.
|
569
|
+
def lookupvar(name)
|
570
|
+
#Puppet.debug "Looking up variable %s" % name
|
571
|
+
value = lookup("variable", name)
|
572
|
+
if value == :undefined
|
573
|
+
return ""
|
574
|
+
#error = Puppet::ParseError.new(
|
575
|
+
# "Undefined variable '%s'" % name
|
576
|
+
#)
|
577
|
+
#raise error
|
578
|
+
else
|
579
|
+
return value
|
584
580
|
end
|
581
|
+
end
|
585
582
|
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
values = {}
|
592
|
-
|
593
|
-
# first collect the values from the parents
|
594
|
-
unless @parent.nil?
|
595
|
-
@parent.lookupdefaults(type).each { |var,value|
|
596
|
-
values[var] = value
|
597
|
-
}
|
598
|
-
end
|
599
|
-
|
600
|
-
# then override them with any current values
|
601
|
-
# this should probably be done differently
|
602
|
-
if @defaultstable.include?(type)
|
603
|
-
@defaultstable[type].each { |var,value|
|
604
|
-
values[var] = value
|
605
|
-
}
|
606
|
-
end
|
607
|
-
#Puppet.debug "Got defaults for %s: %s" %
|
608
|
-
# [type,values.inspect]
|
609
|
-
return values
|
583
|
+
# Add a new object to our object table.
|
584
|
+
def newobject(hash)
|
585
|
+
if @objectable[hash[:type]].include?(hash[:name])
|
586
|
+
raise Puppet::DevError, "Object %s[%s] is already defined" %
|
587
|
+
[hash[:type], hash[:name]]
|
610
588
|
end
|
611
589
|
|
612
|
-
|
613
|
-
def lookupnode(name)
|
614
|
-
#Puppet.debug "Looking up type %s" % name
|
615
|
-
value = self.lookup("type",name)
|
616
|
-
if value == :undefined
|
617
|
-
return nil
|
618
|
-
else
|
619
|
-
#Puppet.debug "Found node %s" % name
|
620
|
-
return value
|
621
|
-
end
|
622
|
-
end
|
590
|
+
self.chkobjectclosure(hash)
|
623
591
|
|
624
|
-
|
625
|
-
def lookuptype(name)
|
626
|
-
#Puppet.debug "Looking up type %s" % name
|
627
|
-
value = self.lookup("type",name)
|
628
|
-
if value == :undefined
|
629
|
-
return nil
|
630
|
-
else
|
631
|
-
#Puppet.debug "Found type %s" % name
|
632
|
-
return value
|
633
|
-
end
|
634
|
-
end
|
592
|
+
obj = nil
|
635
593
|
|
636
|
-
#
|
637
|
-
#
|
638
|
-
|
639
|
-
|
640
|
-
name = hash[:name]
|
641
|
-
#Puppet.debug "Looking up object %s of type %s in level %s" %
|
642
|
-
# [name, type, @level]
|
643
|
-
sub = proc { |table|
|
644
|
-
if table.include?(type)
|
645
|
-
if table[type].include?(name)
|
646
|
-
table[type][name]
|
647
|
-
end
|
648
|
-
else
|
649
|
-
nil
|
650
|
-
end
|
651
|
-
}
|
652
|
-
value = self.lookup("object",sub, true)
|
653
|
-
if value == :undefined
|
654
|
-
return nil
|
655
|
-
else
|
656
|
-
return value
|
657
|
-
end
|
658
|
-
end
|
594
|
+
# If it's a builtin type, then use a transobject, else use
|
595
|
+
# a ScopeObj, which will get replaced later.
|
596
|
+
if self.builtintype?(hash[:type])
|
597
|
+
obj = Puppet::TransObject.new(hash[:name], hash[:type])
|
659
598
|
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
error = Puppet::ParseError.new(
|
666
|
-
"Undefined variable '%s'" % name
|
667
|
-
)
|
668
|
-
raise error
|
669
|
-
else
|
670
|
-
return value
|
671
|
-
end
|
599
|
+
@children << obj
|
600
|
+
else
|
601
|
+
obj = ScopeObj.new(nil)
|
602
|
+
obj.name = hash[:name]
|
603
|
+
obj.type = hash[:type]
|
672
604
|
end
|
673
605
|
|
674
|
-
|
675
|
-
def newobject(hash)
|
676
|
-
if @objectable[hash[:type]].include?(hash[:name])
|
677
|
-
raise Puppet::DevError, "Object %s[%s] is already defined" %
|
678
|
-
[hash[:type], hash[:name]]
|
679
|
-
end
|
680
|
-
|
681
|
-
self.chkobjectclosure(hash)
|
606
|
+
@objectable[hash[:type]][hash[:name]] = obj
|
682
607
|
|
683
|
-
|
608
|
+
@definedtable[hash[:type]][hash[:name]] = obj
|
684
609
|
|
685
|
-
|
686
|
-
|
687
|
-
if self.builtintype?(hash[:type])
|
688
|
-
obj = TransObject.new(hash[:name], hash[:type])
|
610
|
+
# Keep them in order, just for kicks
|
611
|
+
@objectlist << obj
|
689
612
|
|
690
|
-
|
691
|
-
|
692
|
-
obj = ScopeObj.new(nil)
|
693
|
-
obj.name = hash[:name]
|
694
|
-
obj.type = hash[:type]
|
695
|
-
end
|
613
|
+
return obj
|
614
|
+
end
|
696
615
|
|
697
|
-
|
616
|
+
# Create a new scope.
|
617
|
+
def newscope(hash = {})
|
618
|
+
hash[:parent] = self
|
619
|
+
#debug "Creating new scope, level %s" % [self.level + 1]
|
620
|
+
return Puppet::Parser::Scope.new(hash)
|
621
|
+
end
|
698
622
|
|
699
|
-
|
623
|
+
# Retrieve a specific node. This is used in ast.rb to find a
|
624
|
+
# parent node and in findnode to retrieve and evaluate a node.
|
625
|
+
def node(name)
|
626
|
+
@nodetable[name]
|
627
|
+
end
|
700
628
|
|
701
|
-
|
702
|
-
|
629
|
+
# Store the fact that we've evaluated a given class. We use a hash
|
630
|
+
# that gets inherited from the top scope down, rather than a global
|
631
|
+
# hash. We store the object ID, not class name, so that we
|
632
|
+
# can support multiple unrelated classes with the same name.
|
633
|
+
def setclass(id, name)
|
634
|
+
unless name =~ /^[a-z]\w*$/
|
635
|
+
raise Puppet::ParseError, "Invalid class name '%s'" % name
|
636
|
+
end
|
703
637
|
|
704
|
-
|
638
|
+
if self.topscope?
|
639
|
+
@classtable[id] = name
|
640
|
+
else
|
641
|
+
@parent.setclass(id, name)
|
705
642
|
end
|
643
|
+
end
|
706
644
|
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
645
|
+
# Set defaults for a type. The typename should already be downcased,
|
646
|
+
# so that the syntax is isolated.
|
647
|
+
def setdefaults(type,params)
|
648
|
+
table = @defaultstable[type]
|
649
|
+
|
650
|
+
# if we got a single param, it'll be in its own array
|
651
|
+
unless params[0].is_a?(Array)
|
652
|
+
params = [params]
|
712
653
|
end
|
713
654
|
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
655
|
+
params.each { |ary|
|
656
|
+
#Puppet.debug "Default for %s is %s => %s" %
|
657
|
+
# [type,ary[0].inspect,ary[1].inspect]
|
658
|
+
if @@declarative
|
659
|
+
if table.include?(ary[0])
|
660
|
+
error = Puppet::ParseError.new(
|
661
|
+
"Default already defined for %s { %s }" %
|
662
|
+
[type,ary[0]]
|
663
|
+
)
|
664
|
+
raise error
|
665
|
+
end
|
721
666
|
else
|
722
|
-
|
667
|
+
if table.include?(ary[0])
|
668
|
+
# we should maybe allow this warning to be turned off...
|
669
|
+
Puppet.warning "Replacing default for %s { %s }" %
|
670
|
+
[type,ary[0]]
|
671
|
+
end
|
723
672
|
end
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
# so that the syntax is isolated.
|
728
|
-
def setdefaults(type,params)
|
729
|
-
table = @defaultstable[type]
|
673
|
+
table[ary[0]] = ary[1]
|
674
|
+
}
|
675
|
+
end
|
730
676
|
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
677
|
+
# Store a host in the site node table.
|
678
|
+
def setnode(name,code)
|
679
|
+
unless defined? @nodetable
|
680
|
+
raise Puppet::DevError, "No node table defined"
|
681
|
+
end
|
682
|
+
if @nodetable.include?(name)
|
683
|
+
raise Puppet::ParseError, "Host %s is already defined" % name
|
684
|
+
else
|
685
|
+
#Puppet.warning "Setting node %s at level %s" % [name, @level]
|
735
686
|
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
"Default already defined for %s { %s }" %
|
743
|
-
[type,ary[0]]
|
744
|
-
)
|
745
|
-
raise error
|
746
|
-
end
|
747
|
-
else
|
748
|
-
if table.include?(ary[0])
|
749
|
-
# we should maybe allow this warning to be turned off...
|
750
|
-
Puppet.warning "Replacing default for %s { %s }" %
|
751
|
-
[type,ary[0]]
|
752
|
-
end
|
753
|
-
end
|
754
|
-
table[ary[0]] = ary[1]
|
687
|
+
# We have to store both the scope that's setting the node and
|
688
|
+
# the node itself, so that the node gets evaluated in the correct
|
689
|
+
# scope.
|
690
|
+
@nodetable[name] = {
|
691
|
+
:scope => self,
|
692
|
+
:node => code
|
755
693
|
}
|
756
694
|
end
|
695
|
+
end
|
757
696
|
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
end
|
697
|
+
# Define our type.
|
698
|
+
def settype(name,ltype)
|
699
|
+
# Don't let them redefine the class in this scope.
|
700
|
+
if @typetable.include?(name)
|
701
|
+
raise Puppet::ParseError,
|
702
|
+
"%s is already defined" % name
|
703
|
+
else
|
704
|
+
@typetable[name] = ltype
|
767
705
|
end
|
706
|
+
end
|
768
707
|
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
708
|
+
# This method will fail if the named object is already defined anywhere
|
709
|
+
# in the scope tree, which is what provides some minimal closure-like
|
710
|
+
# behaviour.
|
711
|
+
def setobject(hash)
|
712
|
+
# FIXME This objectlookup stuff should be looking up using both
|
713
|
+
# the name and the namevar.
|
714
|
+
|
715
|
+
# First see if we can look the object up using normal scope
|
716
|
+
# rules, i.e., one of our parent classes has defined the
|
717
|
+
# object or something
|
718
|
+
|
719
|
+
name = hash[:name]
|
720
|
+
type = hash[:type]
|
721
|
+
params = hash[:arguments]
|
722
|
+
file = hash[:file]
|
723
|
+
line = hash[:line]
|
724
|
+
|
725
|
+
# Verify that we're not overriding any already-set parameters.
|
726
|
+
if localobj = @localobjectable[type][name]
|
727
|
+
params.each { |var, value|
|
728
|
+
if localobj.include?(var)
|
729
|
+
msg = "Cannot reassign attribute %s on %s[%s]" %
|
730
|
+
[var, type, name]
|
731
|
+
|
732
|
+
error = Puppet::ParseError.new(msg)
|
733
|
+
error.line = line
|
734
|
+
error.file = file
|
735
|
+
raise error
|
782
736
|
end
|
783
|
-
|
784
|
-
#Puppet.debug("result is '%s'" % newstring)
|
785
|
-
return newstring.gsub(/\\t/, "\t").gsub(/\\n/, "\n").gsub(/\\s/, "\s")
|
737
|
+
}
|
786
738
|
end
|
787
739
|
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
#
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
if localobj.include?(var)
|
809
|
-
msg = "Cannot reassign attribute %s on %s[%s]" %
|
810
|
-
[var, type, name]
|
811
|
-
|
812
|
-
error = Puppet::ParseError.new(msg)
|
813
|
-
error.line = line
|
814
|
-
error.file = file
|
815
|
-
raise error
|
816
|
-
end
|
817
|
-
}
|
818
|
-
end
|
819
|
-
|
820
|
-
if objecttype = self.lookuptype(type)
|
821
|
-
# It's a defined type
|
822
|
-
objecttype.safeevaluate(
|
823
|
-
:name => name,
|
824
|
-
:type => type,
|
825
|
-
:arguments => params,
|
826
|
-
:scope => self
|
827
|
-
)
|
828
|
-
else
|
829
|
-
# First look for it in a parent scope
|
830
|
-
obj = self.lookupobject(:name => name, :type => type)
|
831
|
-
|
832
|
-
unless obj and obj != :undefined
|
833
|
-
unless obj = @objectable[type][name]
|
834
|
-
obj = self.newobject(
|
835
|
-
:type => type,
|
836
|
-
:name => name,
|
837
|
-
:line => line,
|
838
|
-
:file => file
|
839
|
-
)
|
840
|
-
|
841
|
-
# only set these if we've created the object,
|
842
|
-
# which is the most common case
|
843
|
-
# FIXME we eventually need to store the file
|
844
|
-
# and line with each param, not the object
|
845
|
-
# itself.
|
846
|
-
obj.file = file
|
847
|
-
obj.line = line
|
848
|
-
end
|
740
|
+
if objecttype = lookuptype(type)
|
741
|
+
# It's a defined type
|
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
|
+
)
|
849
760
|
|
850
|
-
#
|
851
|
-
#
|
852
|
-
#
|
761
|
+
# only set these if we've created the object,
|
762
|
+
# which is the most common case
|
763
|
+
# FIXME we eventually need to store the file
|
764
|
+
# and line with each param, not the object
|
765
|
+
# itself.
|
766
|
+
obj.file = file
|
767
|
+
obj.line = line
|
853
768
|
end
|
854
|
-
params.each { |var,value|
|
855
|
-
# Add it to our found object
|
856
|
-
obj[var] = value
|
857
|
-
}
|
858
769
|
end
|
859
770
|
|
860
|
-
|
861
|
-
|
771
|
+
# Now add our parameters. This has the function of overriding
|
772
|
+
# existing values, which might have been defined in a higher
|
773
|
+
# scope.
|
862
774
|
params.each { |var,value|
|
863
|
-
#
|
864
|
-
|
775
|
+
# Add it to our found object
|
776
|
+
obj[var] = value
|
865
777
|
}
|
778
|
+
end
|
866
779
|
|
867
|
-
|
780
|
+
@localobjectable[type][name] ||= {}
|
781
|
+
|
782
|
+
params.each { |var,value|
|
783
|
+
# And add it to the local table; mmm, hack
|
784
|
+
@localobjectable[type][name][var] = value
|
785
|
+
}
|
786
|
+
|
787
|
+
return obj
|
788
|
+
end
|
789
|
+
|
790
|
+
# Set a variable in the current scope. This will override settings
|
791
|
+
# in scopes above, but will not allow variables in the current scope
|
792
|
+
# to be reassigned if we're declarative (which is the default).
|
793
|
+
def setvar(name,value)
|
794
|
+
#Puppet.debug "Setting %s to '%s' at level %s" %
|
795
|
+
# [name.inspect,value,self.level]
|
796
|
+
if @@declarative and @symtable.include?(name)
|
797
|
+
raise Puppet::ParseError, "Cannot reassign variable %s" % name
|
798
|
+
else
|
799
|
+
if @symtable.include?(name)
|
800
|
+
Puppet.warning "Reassigning %s to %s" % [name,value]
|
801
|
+
end
|
802
|
+
@symtable[name] = value
|
868
803
|
end
|
804
|
+
end
|
869
805
|
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
if
|
877
|
-
|
806
|
+
# Return an interpolated string.
|
807
|
+
def strinterp(string)
|
808
|
+
newstring = string.dup
|
809
|
+
regex = Regexp.new('\$\{(\w+)\}|\$(\w+)')
|
810
|
+
#Puppet.debug("interpreting '%s'" % string)
|
811
|
+
while match = regex.match(newstring) do
|
812
|
+
if match[1]
|
813
|
+
newstring.sub!(regex,lookupvar(match[1]).to_s)
|
814
|
+
elsif match[2]
|
815
|
+
newstring.sub!(regex,lookupvar(match[2]).to_s)
|
878
816
|
else
|
879
|
-
|
880
|
-
|
881
|
-
end
|
882
|
-
@symtable[name] = value
|
817
|
+
raise Puppet::DevError, "Could not match variable in %s" %
|
818
|
+
newstring
|
883
819
|
end
|
884
820
|
end
|
821
|
+
#Puppet.debug("result is '%s'" % newstring)
|
822
|
+
return newstring.gsub(/\\t/, "\t").gsub(/\\n/, "\n").gsub(/\\s/, "\s")
|
823
|
+
end
|
824
|
+
|
825
|
+
# Add a tag to our current list. These tags will be added to all
|
826
|
+
# of the objects contained in this scope.
|
827
|
+
def tag(*ary)
|
828
|
+
ary.each { |tag|
|
829
|
+
if tag.nil? or tag == ""
|
830
|
+
Puppet.debug "got told to tag with %s" % tag.inspect
|
831
|
+
next
|
832
|
+
end
|
833
|
+
unless @tags.include?(tag)
|
834
|
+
#Puppet.info "Tagging scope %s with %s" % [self.object_id, tag]
|
835
|
+
@tags << tag.to_s
|
836
|
+
end
|
837
|
+
}
|
838
|
+
end
|
885
839
|
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
840
|
+
# Return the tags associated with this scope. It's basically
|
841
|
+
# just our parents' tags, plus our type.
|
842
|
+
def tags
|
843
|
+
tmp = [] + @tags
|
844
|
+
unless ! defined? @type or @type.nil? or @type == ""
|
845
|
+
tmp << @type.to_s
|
846
|
+
end
|
847
|
+
if @parent
|
848
|
+
@parent.tags.each { |tag|
|
890
849
|
if tag.nil? or tag == ""
|
891
|
-
Puppet.debug "
|
850
|
+
Puppet.debug "parent returned tag %s" % tag.inspect
|
892
851
|
next
|
893
852
|
end
|
894
|
-
unless
|
895
|
-
|
896
|
-
@tags << tag.to_s
|
853
|
+
unless tmp.include?(tag)
|
854
|
+
tmp << tag
|
897
855
|
end
|
898
856
|
}
|
899
857
|
end
|
858
|
+
return tmp
|
859
|
+
end
|
900
860
|
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
end
|
908
|
-
if @parent
|
909
|
-
@parent.tags.each { |tag|
|
910
|
-
if tag.nil? or tag == ""
|
911
|
-
Puppet.debug "parent returned tag %s" % tag.inspect
|
912
|
-
next
|
913
|
-
end
|
914
|
-
unless tmp.include?(tag)
|
915
|
-
tmp << tag
|
916
|
-
end
|
917
|
-
}
|
918
|
-
end
|
919
|
-
return tmp
|
861
|
+
# Used mainly for logging
|
862
|
+
def to_s
|
863
|
+
if @name
|
864
|
+
return "%s[%s]" % [@type, @name]
|
865
|
+
else
|
866
|
+
return @type.to_s
|
920
867
|
end
|
868
|
+
end
|
921
869
|
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
870
|
+
# Convert our scope to a list of Transportable objects.
|
871
|
+
def to_trans
|
872
|
+
|
873
|
+
results = []
|
874
|
+
|
875
|
+
# Iterate across our child scopes and call to_trans on them
|
876
|
+
@children.each { |child|
|
877
|
+
if child.is_a?(Scope)
|
878
|
+
cresult = child.to_trans
|
879
|
+
|
880
|
+
# Scopes normally result in a TransBucket, but they could
|
881
|
+
# also result in a normal array; if that happens, get rid
|
882
|
+
# of the array.
|
883
|
+
unless cresult.is_a?(Puppet::TransBucket)
|
884
|
+
cresult.each { |result|
|
885
|
+
results.push(result)
|
886
|
+
}
|
887
|
+
else
|
888
|
+
unless cresult.empty?
|
889
|
+
# Otherwise, just add it to our list of results.
|
890
|
+
results.push(cresult)
|
891
|
+
end
|
892
|
+
end
|
893
|
+
elsif child.is_a?(Puppet::TransObject)
|
894
|
+
if child.empty?
|
895
|
+
next
|
896
|
+
end
|
897
|
+
# Wait until the last minute to set tags, although this
|
898
|
+
# probably should not matter
|
899
|
+
child.tags = self.tags
|
900
|
+
|
901
|
+
# Add any defaults.
|
902
|
+
self.adddefaults(child)
|
903
|
+
|
904
|
+
# Then make sure this child's tags are stored in the
|
905
|
+
# central table. This should maybe be in the evaluate
|
906
|
+
# methods, but, eh.
|
907
|
+
@topscope.addtags(child)
|
908
|
+
results.push(child)
|
926
909
|
else
|
927
|
-
|
910
|
+
raise Puppet::DevError,
|
911
|
+
"Puppet::Parse::Scope cannot handle objects of type %s" %
|
912
|
+
child.class
|
928
913
|
end
|
929
|
-
|
914
|
+
}
|
930
915
|
|
931
|
-
#
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
# self.err "Not finished"
|
936
|
-
# self.finish
|
937
|
-
#end
|
938
|
-
#Puppet.debug "Translating scope %s at level %s" %
|
939
|
-
# [self.object_id,self.level]
|
940
|
-
|
941
|
-
results = []
|
942
|
-
|
943
|
-
# Iterate across our child scopes and call to_trans on them
|
944
|
-
@children.each { |child|
|
945
|
-
if child.is_a?(Scope)
|
946
|
-
cresult = child.to_trans
|
947
|
-
#Puppet.debug "Got %s from scope %s" %
|
948
|
-
# [cresult.class,child.object_id]
|
949
|
-
|
950
|
-
# Scopes normally result in a TransBucket, but they could
|
951
|
-
# also result in a normal array; if that happens, get rid
|
952
|
-
# of the array.
|
953
|
-
unless cresult.is_a?(TransBucket)
|
954
|
-
cresult.each { |result|
|
955
|
-
results.push(result)
|
956
|
-
}
|
957
|
-
else
|
958
|
-
unless cresult.empty?
|
959
|
-
# Otherwise, just add it to our list of results.
|
960
|
-
results.push(cresult)
|
961
|
-
end
|
962
|
-
end
|
916
|
+
# Get rid of any nil objects.
|
917
|
+
results = results.reject { |child|
|
918
|
+
child.nil?
|
919
|
+
}
|
963
920
|
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
end
|
970
|
-
elsif child.is_a?(TransObject)
|
971
|
-
if child.empty?
|
972
|
-
next
|
973
|
-
end
|
974
|
-
# Wait until the last minute to set tags, although this
|
975
|
-
# probably should not matter
|
976
|
-
child.tags = self.tags
|
977
|
-
|
978
|
-
# Then make sure this child's tags are stored in the
|
979
|
-
# central table. This should maybe be in the evaluate
|
980
|
-
# methods, but, eh.
|
981
|
-
@topscope.addtags(child)
|
982
|
-
results.push(child)
|
983
|
-
else
|
984
|
-
raise Puppet::DevError,
|
985
|
-
"Puppet::Parse::Scope cannot handle objects of type %s" %
|
986
|
-
child.class
|
987
|
-
end
|
988
|
-
}
|
921
|
+
# If we have a name and type, then make a TransBucket, which
|
922
|
+
# becomes a component.
|
923
|
+
# Else, just stack all of the objects into the current bucket.
|
924
|
+
if @type
|
925
|
+
bucket = Puppet::TransBucket.new
|
989
926
|
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
}
|
927
|
+
if defined? @name and @name
|
928
|
+
bucket.name = @name
|
929
|
+
end
|
994
930
|
|
995
|
-
#
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
931
|
+
# it'd be nice not to have to do this...
|
932
|
+
results.each { |result|
|
933
|
+
#Puppet.warning "Result type is %s" % result.class
|
934
|
+
bucket.push(result)
|
935
|
+
}
|
936
|
+
if defined? @type
|
937
|
+
bucket.type = @type
|
938
|
+
else
|
939
|
+
raise Puppet::ParseError,
|
940
|
+
"No type for scope %s" % @name
|
941
|
+
end
|
1000
942
|
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
943
|
+
if defined? @keyword
|
944
|
+
bucket.keyword = @keyword
|
945
|
+
end
|
946
|
+
#Puppet.debug(
|
947
|
+
# "TransBucket with name %s and type %s in scope %s" %
|
948
|
+
# [@name,@type,self.object_id]
|
949
|
+
#)
|
1004
950
|
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
if defined? @type
|
1011
|
-
bucket.type = @type
|
951
|
+
# now find metaparams
|
952
|
+
@symtable.each { |var,value|
|
953
|
+
if Puppet::Type.metaparam?(var.intern)
|
954
|
+
#Puppet.debug("Adding metaparam %s" % var)
|
955
|
+
bucket.param(var,value)
|
1012
956
|
else
|
1013
|
-
|
1014
|
-
"No type for scope %s" % @name
|
957
|
+
#Puppet.debug("%s is not a metaparam" % var)
|
1015
958
|
end
|
959
|
+
}
|
960
|
+
#Puppet.debug "Returning bucket %s from scope %s" %
|
961
|
+
# [bucket.name,self.object_id]
|
962
|
+
return bucket
|
963
|
+
else
|
964
|
+
Puppet.debug "nameless scope; just returning a list"
|
965
|
+
return results
|
966
|
+
end
|
967
|
+
end
|
1016
968
|
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
969
|
+
protected
|
970
|
+
|
971
|
+
# This method abstracts recursive searching. It accepts the type
|
972
|
+
# of search being done and then either a literal key to search for or
|
973
|
+
# a Proc instance to do the searching.
|
974
|
+
def lookup(type,sub, usecontext = false)
|
975
|
+
table = @map[type]
|
976
|
+
if table.nil?
|
977
|
+
error = Puppet::ParseError.new(
|
978
|
+
"Could not retrieve %s table at level %s" %
|
979
|
+
[type,self.level]
|
980
|
+
)
|
981
|
+
raise error
|
982
|
+
end
|
983
|
+
|
984
|
+
if sub.is_a?(Proc) and obj = sub.call(table)
|
985
|
+
return obj
|
986
|
+
elsif table.include?(sub)
|
987
|
+
return table[sub]
|
988
|
+
elsif ! @parent.nil?
|
989
|
+
#self.notice "Context is %s, parent %s is %s" %
|
990
|
+
# [self.context, @parent.type, @parent.context]
|
991
|
+
if usecontext and self.context != @parent.context
|
992
|
+
return :undefined
|
1037
993
|
else
|
1038
|
-
|
1039
|
-
return results
|
994
|
+
return @parent.lookup(type,sub, usecontext)
|
1040
995
|
end
|
996
|
+
else
|
997
|
+
return :undefined
|
1041
998
|
end
|
1042
999
|
end
|
1043
1000
|
end
|
1044
1001
|
end
|
1045
1002
|
|
1046
|
-
# $Id: scope.rb
|
1003
|
+
# $Id: scope.rb 1104 2006-04-11 17:48:14Z luke $
|