puppet 0.9.2 → 0.13.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 +58 -0
- data/README +21 -18
- data/Rakefile +176 -36
- data/bin/puppet +34 -48
- data/bin/puppetca +41 -28
- data/bin/puppetd +87 -65
- data/bin/puppetdoc +99 -23
- data/bin/puppetmasterd +72 -91
- data/conf/redhat/client.init +80 -0
- data/conf/redhat/client.sysconfig +11 -0
- data/conf/redhat/fileserver.conf +12 -0
- data/conf/redhat/puppet.spec +130 -0
- data/conf/redhat/server.init +89 -0
- data/conf/redhat/server.sysconfig +9 -0
- data/examples/code/allatonce +2 -2
- data/examples/code/assignments +1 -1
- data/examples/code/classing +2 -2
- data/examples/code/components +2 -2
- data/examples/code/file.bl +5 -5
- data/examples/code/filedefaults +2 -2
- data/examples/code/fileparsing +1 -1
- data/examples/code/filerecursion +1 -1
- data/examples/code/functions +1 -1
- data/examples/code/groups +1 -1
- data/examples/code/importing +1 -1
- data/examples/code/nodes +1 -1
- data/examples/code/one +1 -1
- data/examples/code/relationships +2 -2
- data/examples/code/simpletests +5 -5
- data/examples/code/snippets/argumentdefaults +2 -2
- data/examples/code/snippets/casestatement +16 -8
- data/examples/code/snippets/classheirarchy.pp +4 -4
- data/examples/code/snippets/classincludes.pp +4 -4
- data/examples/code/snippets/classpathtest +2 -2
- data/examples/code/snippets/componentmetaparams.pp +11 -0
- data/examples/code/snippets/dirchmod +5 -5
- data/examples/code/snippets/emptyclass.pp +9 -0
- data/examples/code/snippets/failmissingexecpath.pp +1 -1
- data/examples/code/snippets/falsevalues.pp +1 -1
- data/examples/code/snippets/filecreate +5 -5
- data/examples/code/snippets/implicititeration +5 -5
- data/examples/code/snippets/multipleinstances +4 -4
- data/examples/code/snippets/namevartest +3 -3
- data/examples/code/snippets/scopetest +1 -1
- data/examples/code/snippets/selectorvalues.pp +3 -3
- data/examples/code/snippets/simpledefaults +2 -2
- data/examples/code/snippets/simpleselector +5 -5
- data/examples/code/snippets/singleary.pp +19 -0
- data/examples/root/etc/init.d/sleeper +3 -2
- data/ext/emacs/puppet-mode-init.el +6 -0
- data/ext/emacs/puppet-mode.el +189 -0
- data/ext/ldap/puppet.schema +17 -0
- data/ext/{module:puppet → module_puppet} +30 -31
- data/ext/vim/filetype.vim +9 -0
- data/ext/vim/puppet.vim +87 -0
- data/install.rb +63 -30
- data/lib/puppet.rb +216 -122
- data/lib/puppet/client.rb +51 -416
- data/lib/puppet/client/ca.rb +17 -0
- data/lib/puppet/client/dipper.rb +78 -0
- data/lib/puppet/client/file.rb +20 -0
- data/lib/puppet/client/log.rb +17 -0
- data/lib/puppet/client/master.rb +246 -0
- data/lib/puppet/client/proxy.rb +27 -0
- data/lib/puppet/client/status.rb +7 -0
- data/lib/puppet/config.rb +563 -13
- data/lib/puppet/daemon.rb +50 -22
- data/lib/puppet/element.rb +4 -4
- data/lib/puppet/event-loop.rb +1 -0
- data/lib/puppet/event-loop/better-definers.rb +367 -0
- data/lib/puppet/event-loop/event-loop.rb +355 -0
- data/lib/puppet/event-loop/signal-system.rb +220 -0
- data/lib/puppet/event.rb +9 -11
- data/lib/puppet/filetype.rb +195 -0
- data/lib/puppet/log.rb +35 -12
- data/lib/puppet/metric.rb +2 -2
- data/lib/puppet/networkclient.rb +145 -0
- data/lib/puppet/parameter.rb +335 -0
- data/lib/puppet/parser/ast.rb +42 -1453
- data/lib/puppet/parser/ast/astarray.rb +88 -0
- data/lib/puppet/parser/ast/branch.rb +47 -0
- data/lib/puppet/parser/ast/caseopt.rb +66 -0
- data/lib/puppet/parser/ast/casestatement.rb +78 -0
- data/lib/puppet/parser/ast/classdef.rb +78 -0
- data/lib/puppet/parser/ast/compdef.rb +111 -0
- data/lib/puppet/parser/ast/component.rb +105 -0
- data/lib/puppet/parser/ast/hostclass.rb +82 -0
- data/lib/puppet/parser/ast/leaf.rb +86 -0
- data/lib/puppet/parser/ast/node.rb +103 -0
- data/lib/puppet/parser/ast/nodedef.rb +68 -0
- data/lib/puppet/parser/ast/objectdef.rb +336 -0
- data/lib/puppet/parser/ast/objectparam.rb +30 -0
- data/lib/puppet/parser/ast/objectref.rb +76 -0
- data/lib/puppet/parser/ast/selector.rb +60 -0
- data/lib/puppet/parser/ast/typedefaults.rb +45 -0
- data/lib/puppet/parser/ast/vardef.rb +44 -0
- data/lib/puppet/parser/interpreter.rb +31 -14
- data/lib/puppet/parser/lexer.rb +2 -4
- data/lib/puppet/parser/parser.rb +332 -242
- data/lib/puppet/parser/scope.rb +55 -38
- data/lib/puppet/server.rb +43 -44
- data/lib/puppet/server/authstore.rb +3 -6
- data/lib/puppet/server/ca.rb +5 -2
- data/lib/puppet/server/filebucket.rb +2 -4
- data/lib/puppet/server/fileserver.rb +28 -12
- data/lib/puppet/server/logger.rb +15 -4
- data/lib/puppet/server/master.rb +62 -7
- data/lib/puppet/sslcertificates.rb +41 -607
- data/lib/puppet/sslcertificates/ca.rb +291 -0
- data/lib/puppet/sslcertificates/certificate.rb +283 -0
- data/lib/puppet/statechange.rb +6 -1
- data/lib/puppet/storage.rb +67 -56
- data/lib/puppet/transaction.rb +25 -9
- data/lib/puppet/transportable.rb +102 -22
- data/lib/puppet/type.rb +1096 -315
- data/lib/puppet/type/component.rb +30 -21
- data/lib/puppet/type/cron.rb +409 -448
- data/lib/puppet/type/exec.rb +234 -174
- data/lib/puppet/type/group.rb +65 -82
- data/lib/puppet/type/nameservice.rb +247 -3
- data/lib/puppet/type/nameservice/netinfo.rb +29 -40
- data/lib/puppet/type/nameservice/objectadd.rb +52 -66
- data/lib/puppet/type/nameservice/posix.rb +6 -194
- data/lib/puppet/type/package.rb +447 -295
- data/lib/puppet/type/package/apt.rb +51 -50
- data/lib/puppet/type/package/bsd.rb +82 -0
- data/lib/puppet/type/package/dpkg.rb +85 -88
- data/lib/puppet/type/package/rpm.rb +67 -63
- data/lib/puppet/type/package/sun.rb +119 -98
- data/lib/puppet/type/package/yum.rb +41 -37
- data/lib/puppet/type/parsedtype.rb +295 -0
- data/lib/puppet/type/parsedtype/host.rb +143 -0
- data/lib/puppet/type/parsedtype/port.rb +232 -0
- data/lib/puppet/type/parsedtype/sshkey.rb +129 -0
- data/lib/puppet/type/pfile.rb +484 -460
- data/lib/puppet/type/pfile/checksum.rb +237 -181
- data/lib/puppet/type/pfile/content.rb +67 -0
- data/lib/puppet/type/pfile/ensure.rb +212 -0
- data/lib/puppet/type/pfile/group.rb +106 -105
- data/lib/puppet/type/pfile/mode.rb +98 -101
- data/lib/puppet/type/pfile/source.rb +228 -209
- data/lib/puppet/type/pfile/type.rb +18 -21
- data/lib/puppet/type/pfile/uid.rb +127 -130
- data/lib/puppet/type/pfilebucket.rb +68 -63
- data/lib/puppet/type/schedule.rb +341 -0
- data/lib/puppet/type/service.rb +351 -255
- data/lib/puppet/type/service/base.rb +9 -14
- data/lib/puppet/type/service/debian.rb +32 -38
- data/lib/puppet/type/service/init.rb +130 -130
- data/lib/puppet/type/service/smf.rb +48 -20
- data/lib/puppet/type/state.rb +229 -16
- data/lib/puppet/type/symlink.rb +51 -63
- data/lib/puppet/type/tidy.rb +105 -102
- data/lib/puppet/type/user.rb +118 -180
- data/lib/puppet/util.rb +100 -6
- data/test/certmgr/certmgr.rb +0 -1
- data/test/client/client.rb +4 -4
- data/test/executables/puppetbin.rb +7 -14
- data/test/executables/puppetca.rb +18 -24
- data/test/executables/puppetd.rb +7 -16
- data/test/executables/puppetmasterd.rb +7 -9
- data/test/executables/puppetmodule.rb +11 -16
- data/test/language/ast.rb +11 -7
- data/test/language/interpreter.rb +1 -1
- data/test/language/scope.rb +2 -0
- data/test/language/snippets.rb +30 -5
- data/test/language/transportable.rb +77 -0
- data/test/other/config.rb +316 -0
- data/test/other/events.rb +22 -21
- data/test/other/log.rb +14 -14
- data/test/other/metrics.rb +4 -8
- data/test/other/overrides.rb +5 -5
- data/test/other/relationships.rb +4 -2
- data/test/other/storage.rb +64 -3
- data/test/other/transactions.rb +20 -20
- data/test/parser/parser.rb +7 -4
- data/test/puppet/conffiles.rb +12 -12
- data/test/puppet/defaults.rb +13 -11
- data/test/puppet/utiltest.rb +14 -11
- data/test/puppettest.rb +156 -48
- data/test/server/bucket.rb +2 -2
- data/test/server/fileserver.rb +6 -6
- data/test/server/logger.rb +19 -11
- data/test/server/master.rb +33 -4
- data/test/server/server.rb +2 -7
- data/test/types/basic.rb +5 -7
- data/test/types/component.rb +22 -18
- data/test/types/cron.rb +111 -44
- data/test/types/exec.rb +116 -59
- data/test/types/file.rb +262 -137
- data/test/types/filebucket.rb +13 -15
- data/test/types/fileignoresource.rb +12 -16
- data/test/types/filesources.rb +73 -48
- data/test/types/filetype.rb +13 -15
- data/test/types/group.rb +15 -13
- data/test/types/host.rb +146 -0
- data/test/types/package.rb +74 -63
- data/test/types/port.rb +139 -0
- data/test/types/query.rb +8 -8
- data/test/types/schedule.rb +335 -0
- data/test/types/service.rb +137 -21
- data/test/types/sshkey.rb +140 -0
- data/test/types/symlink.rb +3 -5
- data/test/types/tidy.rb +5 -14
- data/test/types/type.rb +67 -11
- data/test/types/user.rb +25 -23
- metadata +186 -122
- data/lib/puppet/type/pfile/create.rb +0 -108
- data/lib/puppet/type/pprocess.rb +0 -97
- data/lib/puppet/type/typegen.rb +0 -149
- data/lib/puppet/type/typegen/filerecord.rb +0 -243
- data/lib/puppet/type/typegen/filetype.rb +0 -316
- data/test/other/state.rb +0 -106
@@ -0,0 +1,105 @@
|
|
1
|
+
class Puppet::Parser::AST
|
2
|
+
# Evaluate the stored parse tree for a given component. This will
|
3
|
+
# receive the arguments passed to the component and also the type and
|
4
|
+
# name of the component.
|
5
|
+
class Component < AST::Branch
|
6
|
+
class << self
|
7
|
+
attr_accessor :name
|
8
|
+
end
|
9
|
+
|
10
|
+
# The class name
|
11
|
+
@name = :component
|
12
|
+
|
13
|
+
attr_accessor :name, :args, :code, :scope, :autoname, :keyword
|
14
|
+
|
15
|
+
def evaluate(scope,hash,objtype,objname)
|
16
|
+
|
17
|
+
scope = scope.newscope
|
18
|
+
|
19
|
+
# The type is the component or class name
|
20
|
+
scope.type = objtype
|
21
|
+
|
22
|
+
# The name is the name the user has chosen or that has
|
23
|
+
# been dynamically generated. This is almost never used
|
24
|
+
scope.name = objname
|
25
|
+
|
26
|
+
scope.keyword = self.keyword
|
27
|
+
|
28
|
+
# Retain the fact that we were autonamed, if so
|
29
|
+
if self.autoname
|
30
|
+
scope.autoname = true
|
31
|
+
end
|
32
|
+
|
33
|
+
#if self.is_a?(Node)
|
34
|
+
# scope.isnodescope
|
35
|
+
#end
|
36
|
+
|
37
|
+
# Additionally, add a tag for whatever kind of class
|
38
|
+
# we are
|
39
|
+
scope.tag(objtype)
|
40
|
+
|
41
|
+
unless objname =~ /-\d+/ # it was generated
|
42
|
+
scope.tag(objname)
|
43
|
+
end
|
44
|
+
#scope.base = self.class.name
|
45
|
+
|
46
|
+
|
47
|
+
# define all of the arguments in our local scope
|
48
|
+
if self.args
|
49
|
+
|
50
|
+
# Verify that all required arguments are either present or
|
51
|
+
# have been provided with defaults.
|
52
|
+
# FIXME This should probably also require each parent
|
53
|
+
# class's arguments...
|
54
|
+
self.args.each { |arg, default|
|
55
|
+
unless hash.include?(arg)
|
56
|
+
if defined? default and ! default.nil?
|
57
|
+
hash[arg] = default
|
58
|
+
#Puppet.debug "Got default %s for %s in %s" %
|
59
|
+
# [default.inspect, arg.inspect, objname.inspect]
|
60
|
+
else
|
61
|
+
error = Puppet::ParseError.new(
|
62
|
+
"Must pass %s to %s of type %s" %
|
63
|
+
[arg.inspect,name,objtype]
|
64
|
+
)
|
65
|
+
error.line = self.line
|
66
|
+
error.file = self.file
|
67
|
+
raise error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
# Set each of the provided arguments as variables in the
|
74
|
+
# component's scope.
|
75
|
+
hash["name"] = objname
|
76
|
+
hash.each { |arg,value|
|
77
|
+
begin
|
78
|
+
scope.setvar(arg,hash[arg])
|
79
|
+
rescue Puppet::ParseError => except
|
80
|
+
except.line = self.line
|
81
|
+
except.file = self.file
|
82
|
+
raise except
|
83
|
+
rescue Puppet::ParseError => except
|
84
|
+
except.line = self.line
|
85
|
+
except.file = self.file
|
86
|
+
raise except
|
87
|
+
rescue => except
|
88
|
+
error = Puppet::ParseError.new(except.message)
|
89
|
+
error.line = self.line
|
90
|
+
error.file = self.file
|
91
|
+
error.backtrace = except.backtrace
|
92
|
+
raise error
|
93
|
+
end
|
94
|
+
}
|
95
|
+
|
96
|
+
# Now just evaluate the code with our new bindings.
|
97
|
+
self.code.safeevaluate(scope)
|
98
|
+
|
99
|
+
# We return the scope, so that our children can make their scopes
|
100
|
+
# under ours. This allows them to find our definitions.
|
101
|
+
return scope
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class Puppet::Parser::AST
|
2
|
+
# The code associated with a class. This is different from components
|
3
|
+
# in that each class is a singleton -- only one will exist for a given
|
4
|
+
# node.
|
5
|
+
class HostClass < AST::Component
|
6
|
+
@name = :class
|
7
|
+
attr_accessor :parentclass
|
8
|
+
|
9
|
+
def evaluate(scope,hash,objtype,objname)
|
10
|
+
if scope.lookupclass(@name)
|
11
|
+
Puppet.debug "%s class already evaluated" % @name
|
12
|
+
return nil
|
13
|
+
end
|
14
|
+
|
15
|
+
if tmp = self.evalparent(scope, hash, objname)
|
16
|
+
# Override our scope binding with the parent scope
|
17
|
+
# binding. This is quite hackish, but I can't think
|
18
|
+
# of another way to make sure our scopes end up under
|
19
|
+
# our parent scopes.
|
20
|
+
scope = tmp
|
21
|
+
end
|
22
|
+
|
23
|
+
# just use the Component evaluate method, but change the type
|
24
|
+
# to our own type
|
25
|
+
retval = super(scope,hash,@name,objname)
|
26
|
+
|
27
|
+
# Set the mark after we evaluate, so we don't record it but
|
28
|
+
# then encounter an error
|
29
|
+
scope.setclass(@name)
|
30
|
+
return retval
|
31
|
+
end
|
32
|
+
|
33
|
+
# Evaluate our parent class. Parent classes are evaluated in the
|
34
|
+
# exact same scope as the children. This is maybe not a good idea
|
35
|
+
# but, eh.
|
36
|
+
def evalparent(scope, args, name)
|
37
|
+
if @parentclass
|
38
|
+
parentobj = nil
|
39
|
+
|
40
|
+
begin
|
41
|
+
parentobj = scope.lookuptype(@parentclass)
|
42
|
+
rescue Puppet::ParseError => except
|
43
|
+
except.line = self.line
|
44
|
+
except.file = self.file
|
45
|
+
raise except
|
46
|
+
rescue => detail
|
47
|
+
error = Puppet::ParseError.new(detail)
|
48
|
+
error.line = self.line
|
49
|
+
error.file = self.file
|
50
|
+
raise error
|
51
|
+
end
|
52
|
+
unless parentobj
|
53
|
+
error = Puppet::ParseError.new(
|
54
|
+
"Could not find parent '%s' of '%s'" %
|
55
|
+
[@parentclass,@name])
|
56
|
+
error.line = self.line
|
57
|
+
error.file = self.file
|
58
|
+
raise error
|
59
|
+
end
|
60
|
+
|
61
|
+
# Verify that the parent and child are of the same type
|
62
|
+
unless parentobj.class == self.class
|
63
|
+
error = Puppet::ParseError.new(
|
64
|
+
"Class %s has incompatible parent type, %s vs %s" %
|
65
|
+
[@name, parentobj.class, self.class]
|
66
|
+
)
|
67
|
+
error.file = self.file
|
68
|
+
error.line = self.line
|
69
|
+
raise error
|
70
|
+
end
|
71
|
+
return parentobj.safeevaluate(scope,args,@parentclass,name)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(hash)
|
76
|
+
@parentclass = nil
|
77
|
+
super
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
class Puppet::Parser::AST
|
2
|
+
# The base class for all of the leaves of the parse trees. These
|
3
|
+
# basically just have types and values. Both of these parameters
|
4
|
+
# are simple values, not AST objects.
|
5
|
+
class Leaf < AST
|
6
|
+
attr_accessor :value, :type
|
7
|
+
|
8
|
+
# Return our value.
|
9
|
+
def evaluate(scope)
|
10
|
+
return @value
|
11
|
+
end
|
12
|
+
|
13
|
+
# Print the value in parse tree context.
|
14
|
+
def tree(indent = 0)
|
15
|
+
return ((@@indent * indent) + self.typewrap(self.value))
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
return @value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# The boolean class. True or false. Converts the string it receives
|
24
|
+
# to a Ruby boolean.
|
25
|
+
class Boolean < AST::Leaf
|
26
|
+
|
27
|
+
# Use the parent method, but then convert to a real boolean.
|
28
|
+
def initialize(hash)
|
29
|
+
super
|
30
|
+
|
31
|
+
unless @value == 'true' or @value == 'false'
|
32
|
+
raise Puppet::DevError,
|
33
|
+
"'%s' is not a boolean" % @value
|
34
|
+
end
|
35
|
+
if @value == 'true'
|
36
|
+
@value = true
|
37
|
+
else
|
38
|
+
@value = false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# The base string class.
|
44
|
+
class String < AST::Leaf
|
45
|
+
# Interpolate the string looking for variables, and then return
|
46
|
+
# the result.
|
47
|
+
def evaluate(scope)
|
48
|
+
return scope.strinterp(@value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
#---------------------------------------------------------------
|
52
|
+
|
53
|
+
# The 'default' option on case statements and selectors.
|
54
|
+
class Default < AST::Leaf; end
|
55
|
+
|
56
|
+
# Capitalized words; used mostly for type-defaults, but also
|
57
|
+
# get returned by the lexer any other time an unquoted capitalized
|
58
|
+
# word is found.
|
59
|
+
class Type < AST::Leaf; end
|
60
|
+
|
61
|
+
# Lower-case words.
|
62
|
+
class Name < AST::Leaf; end
|
63
|
+
|
64
|
+
# A simple variable. This object is only used during interpolation;
|
65
|
+
# the VarDef class is used for assignment.
|
66
|
+
class Variable < Name
|
67
|
+
# Looks up the value of the object in the scope tree (does
|
68
|
+
# not include syntactical constructs, like '$' and '{}').
|
69
|
+
def evaluate(scope)
|
70
|
+
begin
|
71
|
+
return scope.lookupvar(@value)
|
72
|
+
rescue Puppet::ParseError => except
|
73
|
+
except.line = self.line
|
74
|
+
except.file = self.file
|
75
|
+
raise except
|
76
|
+
rescue => detail
|
77
|
+
error = Puppet::DevError.new(detail)
|
78
|
+
error.line = self.line
|
79
|
+
error.file = self.file
|
80
|
+
error.backtrace = detail.backtrace
|
81
|
+
raise error
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
class Puppet::Parser::AST
|
2
|
+
# The specific code associated with a host. Nodes are annoyingly unlike
|
3
|
+
# other objects. That's just the way it is, at least for now.
|
4
|
+
class Node < AST::HostClass
|
5
|
+
@name = :node
|
6
|
+
attr_accessor :name, :args, :code, :parentclass
|
7
|
+
|
8
|
+
def evaluate(scope, facts = {})
|
9
|
+
scope = scope.newscope
|
10
|
+
|
11
|
+
# nodes are never instantiated like a normal object,
|
12
|
+
# but we need the type to be the name users would use for
|
13
|
+
# instantiation, otherwise tags don't work out
|
14
|
+
|
15
|
+
# The name has already been evaluated, so it's a normal
|
16
|
+
# string.
|
17
|
+
scope.type = @name
|
18
|
+
scope.name = @name
|
19
|
+
scope.keyword = @keyword
|
20
|
+
|
21
|
+
# Mark this scope as a nodescope, so that classes will be
|
22
|
+
# singletons within it
|
23
|
+
scope.isnodescope
|
24
|
+
|
25
|
+
# Now set all of the facts inside this scope
|
26
|
+
facts.each { |var, value|
|
27
|
+
scope.setvar(var, value)
|
28
|
+
}
|
29
|
+
|
30
|
+
if tmp = self.evalparent(scope)
|
31
|
+
# Again, override our scope with the parent scope, if
|
32
|
+
# there is one.
|
33
|
+
scope = tmp
|
34
|
+
end
|
35
|
+
|
36
|
+
#scope.tag(@name)
|
37
|
+
|
38
|
+
# We never pass the facts to the parent class, because they've
|
39
|
+
# already been defined at this top-level scope.
|
40
|
+
#super(scope, facts, @name, @name)
|
41
|
+
|
42
|
+
# And then evaluate our code.
|
43
|
+
@code.safeevaluate(scope)
|
44
|
+
|
45
|
+
return scope
|
46
|
+
end
|
47
|
+
|
48
|
+
# Evaluate our parent class.
|
49
|
+
def evalparent(scope)
|
50
|
+
if @parentclass
|
51
|
+
# This is pretty messed up. I don't know if this will
|
52
|
+
# work in the long term, but we need to evaluate the node
|
53
|
+
# in our own scope, even though our parent node has
|
54
|
+
# a scope associated with it, because otherwise we 1) won't
|
55
|
+
# get our facts defined, and 2) we won't actually get the
|
56
|
+
# objects returned, based on how nodes work.
|
57
|
+
|
58
|
+
# We also can't just evaluate the node itself, because
|
59
|
+
# it would create a node scope within this scope,
|
60
|
+
# and that would cause mass havoc.
|
61
|
+
node = nil
|
62
|
+
|
63
|
+
# The 'node' method just returns a hash of the node
|
64
|
+
# code and name. It's used here, and in 'evalnode'.
|
65
|
+
unless hash = scope.node(@parentclass)
|
66
|
+
raise Puppet::ParseError,
|
67
|
+
"Could not find parent node %s" %
|
68
|
+
@parentclass
|
69
|
+
end
|
70
|
+
|
71
|
+
node = hash[:node]
|
72
|
+
# Tag the scope with the parent's name/type.
|
73
|
+
name = node.name
|
74
|
+
#Puppet.info "Tagging with parent node %s" % name
|
75
|
+
scope.tag(name)
|
76
|
+
|
77
|
+
begin
|
78
|
+
code = node.code
|
79
|
+
code.safeevaluate(scope)
|
80
|
+
rescue Puppet::ParseError => except
|
81
|
+
except.line = self.line
|
82
|
+
except.file = self.file
|
83
|
+
raise except
|
84
|
+
rescue => detail
|
85
|
+
error = Puppet::ParseError.new(detail)
|
86
|
+
error.line = self.line
|
87
|
+
error.file = self.file
|
88
|
+
raise error
|
89
|
+
end
|
90
|
+
|
91
|
+
if node.parentclass
|
92
|
+
node.evalparent(scope)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def initialize(hash)
|
98
|
+
@parentclass = nil
|
99
|
+
super
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class Puppet::Parser::AST
|
2
|
+
# Define a node. The node definition stores a parse tree for each
|
3
|
+
# specified node, and this parse tree is only ever looked up when
|
4
|
+
# a client connects.
|
5
|
+
class NodeDef < AST::Branch
|
6
|
+
attr_accessor :names, :code, :parentclass, :keyword
|
7
|
+
|
8
|
+
def each
|
9
|
+
[@names,@code].each { |child| yield child }
|
10
|
+
end
|
11
|
+
|
12
|
+
# Do implicit iteration over each of the names passed.
|
13
|
+
def evaluate(scope)
|
14
|
+
names = @names.safeevaluate(scope)
|
15
|
+
|
16
|
+
unless names.is_a?(Array)
|
17
|
+
names = [names]
|
18
|
+
end
|
19
|
+
|
20
|
+
names.each { |name|
|
21
|
+
#Puppet.debug("defining host '%s' in scope %s" %
|
22
|
+
# [name, scope.object_id])
|
23
|
+
arghash = {
|
24
|
+
:name => name,
|
25
|
+
:code => @code
|
26
|
+
}
|
27
|
+
|
28
|
+
if @parentclass
|
29
|
+
arghash[:parentclass] = @parentclass.safeevaluate(scope)
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
node = Node.new(arghash)
|
34
|
+
node.keyword = true
|
35
|
+
scope.setnode(name, node)
|
36
|
+
rescue Puppet::ParseError => except
|
37
|
+
except.line = self.line
|
38
|
+
except.file = self.file
|
39
|
+
raise except
|
40
|
+
rescue => detail
|
41
|
+
error = Puppet::ParseError.new(detail)
|
42
|
+
error.line = self.line
|
43
|
+
error.file = self.file
|
44
|
+
raise error
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(hash)
|
50
|
+
@parentclass = nil
|
51
|
+
@keyword = "node"
|
52
|
+
super
|
53
|
+
end
|
54
|
+
|
55
|
+
def tree(indent = 0)
|
56
|
+
return [
|
57
|
+
@names.tree(indent + 1),
|
58
|
+
((@@indline * 4 * indent) + self.typewrap("node")),
|
59
|
+
@code.tree(indent + 1),
|
60
|
+
].join("\n")
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_s
|
64
|
+
return "node %s {\n%s }" % [@name, @code]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,336 @@
|
|
1
|
+
class Puppet::Parser::AST
|
2
|
+
# Any normal puppet object declaration. Can result in a class or a
|
3
|
+
# component, in addition to builtin types.
|
4
|
+
class ObjectDef < AST::Branch
|
5
|
+
attr_accessor :name, :type
|
6
|
+
attr_reader :params
|
7
|
+
|
8
|
+
# probably not used at all
|
9
|
+
def []=(index,obj)
|
10
|
+
@params[index] = obj
|
11
|
+
end
|
12
|
+
|
13
|
+
# probably not used at all
|
14
|
+
def [](index)
|
15
|
+
return @params[index]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Auto-generate a name
|
19
|
+
def autoname(type, object)
|
20
|
+
case object
|
21
|
+
when Puppet::Type:
|
22
|
+
raise Puppet::Error,
|
23
|
+
"Built-in types must be provided with a name"
|
24
|
+
when HostClass:
|
25
|
+
return type
|
26
|
+
else
|
27
|
+
Puppet.info "Autogenerating name for object of type %s" %
|
28
|
+
type
|
29
|
+
return [type, "-", self.object_id].join("")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Iterate across all of our children.
|
34
|
+
def each
|
35
|
+
[@type,@name,@params].flatten.each { |param|
|
36
|
+
#Puppet.debug("yielding param %s" % param)
|
37
|
+
yield param
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Does not actually return an object; instead sets an object
|
42
|
+
# in the current scope.
|
43
|
+
def evaluate(scope)
|
44
|
+
hash = {}
|
45
|
+
|
46
|
+
# Get our type and name.
|
47
|
+
objtype = @type.safeevaluate(scope)
|
48
|
+
|
49
|
+
# If the type was a variable, we wouldn't have typechecked yet.
|
50
|
+
# Do it now, if so.
|
51
|
+
unless @checked
|
52
|
+
self.typecheck(objtype)
|
53
|
+
end
|
54
|
+
|
55
|
+
# See if our object type was defined
|
56
|
+
begin
|
57
|
+
object = scope.lookuptype(objtype)
|
58
|
+
rescue Puppet::ParseError => except
|
59
|
+
except.line = self.line
|
60
|
+
except.file = self.file
|
61
|
+
raise except
|
62
|
+
rescue => detail
|
63
|
+
error = Puppet::ParseError.new(detail)
|
64
|
+
error.line = self.line
|
65
|
+
error.file = self.file
|
66
|
+
error.backtrace = detail.backtrace
|
67
|
+
raise error
|
68
|
+
end
|
69
|
+
|
70
|
+
unless object
|
71
|
+
# If not, verify that it's a builtin type
|
72
|
+
object = Puppet::Type.type(objtype)
|
73
|
+
|
74
|
+
# Type.type returns nil on object types that aren't found
|
75
|
+
unless object
|
76
|
+
error = Puppet::ParseError.new("Invalid type %s" % objtype)
|
77
|
+
error.line = self.line
|
78
|
+
error.file = self.file
|
79
|
+
raise error
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
autonamed = false
|
85
|
+
# Autogenerate the name if one was not passed.
|
86
|
+
if defined? @name
|
87
|
+
objnames = @name.safeevaluate(scope)
|
88
|
+
else
|
89
|
+
objnames = self.autoname(objtype, object)
|
90
|
+
autonamed = true
|
91
|
+
end
|
92
|
+
|
93
|
+
# it's easier to always use an array, even for only one name
|
94
|
+
unless objnames.is_a?(Array)
|
95
|
+
objnames = [objnames]
|
96
|
+
end
|
97
|
+
|
98
|
+
# Retrieve the defaults for our type
|
99
|
+
hash = getdefaults(objtype, scope)
|
100
|
+
|
101
|
+
# then set all of the specified params
|
102
|
+
@params.each { |param|
|
103
|
+
ary = param.safeevaluate(scope)
|
104
|
+
hash[ary[0]] = ary[1]
|
105
|
+
}
|
106
|
+
|
107
|
+
# this is where our implicit iteration takes place;
|
108
|
+
# if someone passed an array as the name, then we act
|
109
|
+
# just like the called us many times
|
110
|
+
objnames.collect { |objname|
|
111
|
+
# If the object is a class, that means it's a builtin type, so
|
112
|
+
# we just store it in the scope
|
113
|
+
if object.is_a?(Class)
|
114
|
+
begin
|
115
|
+
#Puppet.debug(
|
116
|
+
# ("Setting object '%s' " +
|
117
|
+
# "in scope %s " +
|
118
|
+
# "with arguments %s") %
|
119
|
+
# [objname, scope.object_id, hash.inspect]
|
120
|
+
#)
|
121
|
+
obj = scope.setobject(
|
122
|
+
objtype,
|
123
|
+
objname,
|
124
|
+
hash,
|
125
|
+
@file,
|
126
|
+
@line
|
127
|
+
)
|
128
|
+
rescue Puppet::ParseError => except
|
129
|
+
except.line = self.line
|
130
|
+
except.file = self.file
|
131
|
+
raise except
|
132
|
+
rescue => detail
|
133
|
+
error = Puppet::ParseError.new(detail)
|
134
|
+
error.line = self.line
|
135
|
+
error.file = self.file
|
136
|
+
error.backtrace = detail.backtrace
|
137
|
+
raise error
|
138
|
+
end
|
139
|
+
else
|
140
|
+
# but things like components create a new type; if we find
|
141
|
+
# one of those, evaluate that with our arguments
|
142
|
+
#Puppet.debug("Calling object '%s' with arguments %s" %
|
143
|
+
# [object.name, hash.inspect])
|
144
|
+
obj = object.safeevaluate(scope,hash,objtype,objname)
|
145
|
+
|
146
|
+
# Retain any name generation stuff
|
147
|
+
obj.autoname = autonamed
|
148
|
+
|
149
|
+
# and pass the result on
|
150
|
+
obj
|
151
|
+
end
|
152
|
+
}.reject { |obj| obj.nil? }
|
153
|
+
end
|
154
|
+
|
155
|
+
# Retrieve the defaults for our type
|
156
|
+
def getdefaults(objtype, scope)
|
157
|
+
# first, retrieve the defaults
|
158
|
+
begin
|
159
|
+
defaults = scope.lookupdefaults(objtype)
|
160
|
+
if defaults.length > 0
|
161
|
+
#Puppet.debug "Got defaults for %s: %s" %
|
162
|
+
# [objtype,defaults.inspect]
|
163
|
+
end
|
164
|
+
rescue => detail
|
165
|
+
raise Puppet::DevError,
|
166
|
+
"Could not lookup defaults for %s: %s" %
|
167
|
+
[objtype, detail.to_s]
|
168
|
+
end
|
169
|
+
|
170
|
+
hash = {}
|
171
|
+
# Add any found defaults to our argument list
|
172
|
+
defaults.each { |var,value|
|
173
|
+
Puppet.debug "Found default %s for %s" %
|
174
|
+
[var,objtype]
|
175
|
+
|
176
|
+
hash[var] = value
|
177
|
+
}
|
178
|
+
|
179
|
+
return hash
|
180
|
+
end
|
181
|
+
|
182
|
+
# Create our ObjectDef. Handles type checking for us.
|
183
|
+
def initialize(hash)
|
184
|
+
@checked = false
|
185
|
+
super
|
186
|
+
|
187
|
+
if @type.is_a?(Variable)
|
188
|
+
Puppet.debug "Delaying typecheck"
|
189
|
+
return
|
190
|
+
else
|
191
|
+
self.typecheck(@type.value)
|
192
|
+
|
193
|
+
objtype = @type.value
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
# Verify that all passed parameters are valid
|
199
|
+
def paramcheck(builtin, objtype)
|
200
|
+
# This defaults to true
|
201
|
+
unless Puppet[:paramcheck]
|
202
|
+
return
|
203
|
+
end
|
204
|
+
|
205
|
+
@params.each { |param|
|
206
|
+
if builtin
|
207
|
+
self.parambuiltincheck(builtin, param)
|
208
|
+
else
|
209
|
+
self.paramdefinedcheck(objtype, param)
|
210
|
+
end
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
def parambuiltincheck(type, param)
|
215
|
+
unless param.is_a?(AST::ObjectParam)
|
216
|
+
raise Puppet::DevError,
|
217
|
+
"Got something other than param"
|
218
|
+
end
|
219
|
+
begin
|
220
|
+
pname = param.param.value
|
221
|
+
rescue => detail
|
222
|
+
raise Puppet::DevError, detail.to_s
|
223
|
+
end
|
224
|
+
return if pname == "name" # always allow these
|
225
|
+
unless type.validattr?(pname)
|
226
|
+
error = Puppet::ParseError.new(
|
227
|
+
"Invalid parameter '%s' for type '%s'" %
|
228
|
+
[pname,type.name]
|
229
|
+
)
|
230
|
+
error.line = self.line
|
231
|
+
error.file = self.file
|
232
|
+
raise error
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def paramdefinedcheck(objtype, param)
|
237
|
+
# FIXME we might need to do more here eventually...
|
238
|
+
if Puppet::Type.metaparam?(param.param.value.intern)
|
239
|
+
return
|
240
|
+
end
|
241
|
+
|
242
|
+
begin
|
243
|
+
pname = param.param.value
|
244
|
+
rescue => detail
|
245
|
+
raise Puppet::DevError, detail.to_s
|
246
|
+
end
|
247
|
+
|
248
|
+
unless @@settypes[objtype].validarg?(pname)
|
249
|
+
error = Puppet::ParseError.new(
|
250
|
+
"Invalid parameter '%s' for type '%s'" %
|
251
|
+
[pname,objtype]
|
252
|
+
)
|
253
|
+
error.line = self.line
|
254
|
+
error.file = self.file
|
255
|
+
raise error
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Set the parameters for our object.
|
260
|
+
def params=(params)
|
261
|
+
if params.is_a?(AST::ASTArray)
|
262
|
+
@params = params
|
263
|
+
else
|
264
|
+
@params = AST::ASTArray.new(
|
265
|
+
:line => params.line,
|
266
|
+
:file => params.file,
|
267
|
+
:children => [params]
|
268
|
+
)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
# Print this object out.
|
273
|
+
def tree(indent = 0)
|
274
|
+
return [
|
275
|
+
@type.tree(indent + 1),
|
276
|
+
@name.tree(indent + 1),
|
277
|
+
((@@indline * indent) + self.typewrap(self.pin)),
|
278
|
+
@params.collect { |param|
|
279
|
+
begin
|
280
|
+
param.tree(indent + 1)
|
281
|
+
rescue NoMethodError => detail
|
282
|
+
Puppet.err @params.inspect
|
283
|
+
error = Puppet::DevError.new(
|
284
|
+
"failed to tree a %s" % self.class
|
285
|
+
)
|
286
|
+
error.backtrace = detail.backtrace
|
287
|
+
raise error
|
288
|
+
end
|
289
|
+
}.join("\n")
|
290
|
+
].join("\n")
|
291
|
+
end
|
292
|
+
|
293
|
+
# Verify that the type is valid. This throws an error if there's
|
294
|
+
# a problem, so the return value doesn't matter
|
295
|
+
def typecheck(objtype)
|
296
|
+
# This will basically always be on, but I wanted to make it at
|
297
|
+
# least simple to turn off if it came to that
|
298
|
+
unless Puppet[:typecheck]
|
299
|
+
return
|
300
|
+
end
|
301
|
+
|
302
|
+
builtin = false
|
303
|
+
begin
|
304
|
+
builtin = Puppet::Type.type(objtype)
|
305
|
+
rescue TypeError
|
306
|
+
# nothing; we've already set builtin to false
|
307
|
+
end
|
308
|
+
|
309
|
+
unless builtin or @@settypes.include?(objtype)
|
310
|
+
error = Puppet::ParseError.new(
|
311
|
+
"Unknown type '%s'" % objtype
|
312
|
+
)
|
313
|
+
error.line = self.line
|
314
|
+
error.file = self.file
|
315
|
+
raise error
|
316
|
+
end
|
317
|
+
|
318
|
+
#unless builtin
|
319
|
+
# Puppet.debug "%s is a defined type" % objtype
|
320
|
+
#end
|
321
|
+
|
322
|
+
self.paramcheck(builtin, objtype)
|
323
|
+
|
324
|
+
@checked = true
|
325
|
+
end
|
326
|
+
|
327
|
+
def to_s
|
328
|
+
return "%s => { %s }" % [@name,
|
329
|
+
@params.collect { |param|
|
330
|
+
param.to_s
|
331
|
+
}.join("\n")
|
332
|
+
]
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
end
|