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.

Files changed (213) hide show
  1. data/CHANGELOG +58 -0
  2. data/README +21 -18
  3. data/Rakefile +176 -36
  4. data/bin/puppet +34 -48
  5. data/bin/puppetca +41 -28
  6. data/bin/puppetd +87 -65
  7. data/bin/puppetdoc +99 -23
  8. data/bin/puppetmasterd +72 -91
  9. data/conf/redhat/client.init +80 -0
  10. data/conf/redhat/client.sysconfig +11 -0
  11. data/conf/redhat/fileserver.conf +12 -0
  12. data/conf/redhat/puppet.spec +130 -0
  13. data/conf/redhat/server.init +89 -0
  14. data/conf/redhat/server.sysconfig +9 -0
  15. data/examples/code/allatonce +2 -2
  16. data/examples/code/assignments +1 -1
  17. data/examples/code/classing +2 -2
  18. data/examples/code/components +2 -2
  19. data/examples/code/file.bl +5 -5
  20. data/examples/code/filedefaults +2 -2
  21. data/examples/code/fileparsing +1 -1
  22. data/examples/code/filerecursion +1 -1
  23. data/examples/code/functions +1 -1
  24. data/examples/code/groups +1 -1
  25. data/examples/code/importing +1 -1
  26. data/examples/code/nodes +1 -1
  27. data/examples/code/one +1 -1
  28. data/examples/code/relationships +2 -2
  29. data/examples/code/simpletests +5 -5
  30. data/examples/code/snippets/argumentdefaults +2 -2
  31. data/examples/code/snippets/casestatement +16 -8
  32. data/examples/code/snippets/classheirarchy.pp +4 -4
  33. data/examples/code/snippets/classincludes.pp +4 -4
  34. data/examples/code/snippets/classpathtest +2 -2
  35. data/examples/code/snippets/componentmetaparams.pp +11 -0
  36. data/examples/code/snippets/dirchmod +5 -5
  37. data/examples/code/snippets/emptyclass.pp +9 -0
  38. data/examples/code/snippets/failmissingexecpath.pp +1 -1
  39. data/examples/code/snippets/falsevalues.pp +1 -1
  40. data/examples/code/snippets/filecreate +5 -5
  41. data/examples/code/snippets/implicititeration +5 -5
  42. data/examples/code/snippets/multipleinstances +4 -4
  43. data/examples/code/snippets/namevartest +3 -3
  44. data/examples/code/snippets/scopetest +1 -1
  45. data/examples/code/snippets/selectorvalues.pp +3 -3
  46. data/examples/code/snippets/simpledefaults +2 -2
  47. data/examples/code/snippets/simpleselector +5 -5
  48. data/examples/code/snippets/singleary.pp +19 -0
  49. data/examples/root/etc/init.d/sleeper +3 -2
  50. data/ext/emacs/puppet-mode-init.el +6 -0
  51. data/ext/emacs/puppet-mode.el +189 -0
  52. data/ext/ldap/puppet.schema +17 -0
  53. data/ext/{module:puppet → module_puppet} +30 -31
  54. data/ext/vim/filetype.vim +9 -0
  55. data/ext/vim/puppet.vim +87 -0
  56. data/install.rb +63 -30
  57. data/lib/puppet.rb +216 -122
  58. data/lib/puppet/client.rb +51 -416
  59. data/lib/puppet/client/ca.rb +17 -0
  60. data/lib/puppet/client/dipper.rb +78 -0
  61. data/lib/puppet/client/file.rb +20 -0
  62. data/lib/puppet/client/log.rb +17 -0
  63. data/lib/puppet/client/master.rb +246 -0
  64. data/lib/puppet/client/proxy.rb +27 -0
  65. data/lib/puppet/client/status.rb +7 -0
  66. data/lib/puppet/config.rb +563 -13
  67. data/lib/puppet/daemon.rb +50 -22
  68. data/lib/puppet/element.rb +4 -4
  69. data/lib/puppet/event-loop.rb +1 -0
  70. data/lib/puppet/event-loop/better-definers.rb +367 -0
  71. data/lib/puppet/event-loop/event-loop.rb +355 -0
  72. data/lib/puppet/event-loop/signal-system.rb +220 -0
  73. data/lib/puppet/event.rb +9 -11
  74. data/lib/puppet/filetype.rb +195 -0
  75. data/lib/puppet/log.rb +35 -12
  76. data/lib/puppet/metric.rb +2 -2
  77. data/lib/puppet/networkclient.rb +145 -0
  78. data/lib/puppet/parameter.rb +335 -0
  79. data/lib/puppet/parser/ast.rb +42 -1453
  80. data/lib/puppet/parser/ast/astarray.rb +88 -0
  81. data/lib/puppet/parser/ast/branch.rb +47 -0
  82. data/lib/puppet/parser/ast/caseopt.rb +66 -0
  83. data/lib/puppet/parser/ast/casestatement.rb +78 -0
  84. data/lib/puppet/parser/ast/classdef.rb +78 -0
  85. data/lib/puppet/parser/ast/compdef.rb +111 -0
  86. data/lib/puppet/parser/ast/component.rb +105 -0
  87. data/lib/puppet/parser/ast/hostclass.rb +82 -0
  88. data/lib/puppet/parser/ast/leaf.rb +86 -0
  89. data/lib/puppet/parser/ast/node.rb +103 -0
  90. data/lib/puppet/parser/ast/nodedef.rb +68 -0
  91. data/lib/puppet/parser/ast/objectdef.rb +336 -0
  92. data/lib/puppet/parser/ast/objectparam.rb +30 -0
  93. data/lib/puppet/parser/ast/objectref.rb +76 -0
  94. data/lib/puppet/parser/ast/selector.rb +60 -0
  95. data/lib/puppet/parser/ast/typedefaults.rb +45 -0
  96. data/lib/puppet/parser/ast/vardef.rb +44 -0
  97. data/lib/puppet/parser/interpreter.rb +31 -14
  98. data/lib/puppet/parser/lexer.rb +2 -4
  99. data/lib/puppet/parser/parser.rb +332 -242
  100. data/lib/puppet/parser/scope.rb +55 -38
  101. data/lib/puppet/server.rb +43 -44
  102. data/lib/puppet/server/authstore.rb +3 -6
  103. data/lib/puppet/server/ca.rb +5 -2
  104. data/lib/puppet/server/filebucket.rb +2 -4
  105. data/lib/puppet/server/fileserver.rb +28 -12
  106. data/lib/puppet/server/logger.rb +15 -4
  107. data/lib/puppet/server/master.rb +62 -7
  108. data/lib/puppet/sslcertificates.rb +41 -607
  109. data/lib/puppet/sslcertificates/ca.rb +291 -0
  110. data/lib/puppet/sslcertificates/certificate.rb +283 -0
  111. data/lib/puppet/statechange.rb +6 -1
  112. data/lib/puppet/storage.rb +67 -56
  113. data/lib/puppet/transaction.rb +25 -9
  114. data/lib/puppet/transportable.rb +102 -22
  115. data/lib/puppet/type.rb +1096 -315
  116. data/lib/puppet/type/component.rb +30 -21
  117. data/lib/puppet/type/cron.rb +409 -448
  118. data/lib/puppet/type/exec.rb +234 -174
  119. data/lib/puppet/type/group.rb +65 -82
  120. data/lib/puppet/type/nameservice.rb +247 -3
  121. data/lib/puppet/type/nameservice/netinfo.rb +29 -40
  122. data/lib/puppet/type/nameservice/objectadd.rb +52 -66
  123. data/lib/puppet/type/nameservice/posix.rb +6 -194
  124. data/lib/puppet/type/package.rb +447 -295
  125. data/lib/puppet/type/package/apt.rb +51 -50
  126. data/lib/puppet/type/package/bsd.rb +82 -0
  127. data/lib/puppet/type/package/dpkg.rb +85 -88
  128. data/lib/puppet/type/package/rpm.rb +67 -63
  129. data/lib/puppet/type/package/sun.rb +119 -98
  130. data/lib/puppet/type/package/yum.rb +41 -37
  131. data/lib/puppet/type/parsedtype.rb +295 -0
  132. data/lib/puppet/type/parsedtype/host.rb +143 -0
  133. data/lib/puppet/type/parsedtype/port.rb +232 -0
  134. data/lib/puppet/type/parsedtype/sshkey.rb +129 -0
  135. data/lib/puppet/type/pfile.rb +484 -460
  136. data/lib/puppet/type/pfile/checksum.rb +237 -181
  137. data/lib/puppet/type/pfile/content.rb +67 -0
  138. data/lib/puppet/type/pfile/ensure.rb +212 -0
  139. data/lib/puppet/type/pfile/group.rb +106 -105
  140. data/lib/puppet/type/pfile/mode.rb +98 -101
  141. data/lib/puppet/type/pfile/source.rb +228 -209
  142. data/lib/puppet/type/pfile/type.rb +18 -21
  143. data/lib/puppet/type/pfile/uid.rb +127 -130
  144. data/lib/puppet/type/pfilebucket.rb +68 -63
  145. data/lib/puppet/type/schedule.rb +341 -0
  146. data/lib/puppet/type/service.rb +351 -255
  147. data/lib/puppet/type/service/base.rb +9 -14
  148. data/lib/puppet/type/service/debian.rb +32 -38
  149. data/lib/puppet/type/service/init.rb +130 -130
  150. data/lib/puppet/type/service/smf.rb +48 -20
  151. data/lib/puppet/type/state.rb +229 -16
  152. data/lib/puppet/type/symlink.rb +51 -63
  153. data/lib/puppet/type/tidy.rb +105 -102
  154. data/lib/puppet/type/user.rb +118 -180
  155. data/lib/puppet/util.rb +100 -6
  156. data/test/certmgr/certmgr.rb +0 -1
  157. data/test/client/client.rb +4 -4
  158. data/test/executables/puppetbin.rb +7 -14
  159. data/test/executables/puppetca.rb +18 -24
  160. data/test/executables/puppetd.rb +7 -16
  161. data/test/executables/puppetmasterd.rb +7 -9
  162. data/test/executables/puppetmodule.rb +11 -16
  163. data/test/language/ast.rb +11 -7
  164. data/test/language/interpreter.rb +1 -1
  165. data/test/language/scope.rb +2 -0
  166. data/test/language/snippets.rb +30 -5
  167. data/test/language/transportable.rb +77 -0
  168. data/test/other/config.rb +316 -0
  169. data/test/other/events.rb +22 -21
  170. data/test/other/log.rb +14 -14
  171. data/test/other/metrics.rb +4 -8
  172. data/test/other/overrides.rb +5 -5
  173. data/test/other/relationships.rb +4 -2
  174. data/test/other/storage.rb +64 -3
  175. data/test/other/transactions.rb +20 -20
  176. data/test/parser/parser.rb +7 -4
  177. data/test/puppet/conffiles.rb +12 -12
  178. data/test/puppet/defaults.rb +13 -11
  179. data/test/puppet/utiltest.rb +14 -11
  180. data/test/puppettest.rb +156 -48
  181. data/test/server/bucket.rb +2 -2
  182. data/test/server/fileserver.rb +6 -6
  183. data/test/server/logger.rb +19 -11
  184. data/test/server/master.rb +33 -4
  185. data/test/server/server.rb +2 -7
  186. data/test/types/basic.rb +5 -7
  187. data/test/types/component.rb +22 -18
  188. data/test/types/cron.rb +111 -44
  189. data/test/types/exec.rb +116 -59
  190. data/test/types/file.rb +262 -137
  191. data/test/types/filebucket.rb +13 -15
  192. data/test/types/fileignoresource.rb +12 -16
  193. data/test/types/filesources.rb +73 -48
  194. data/test/types/filetype.rb +13 -15
  195. data/test/types/group.rb +15 -13
  196. data/test/types/host.rb +146 -0
  197. data/test/types/package.rb +74 -63
  198. data/test/types/port.rb +139 -0
  199. data/test/types/query.rb +8 -8
  200. data/test/types/schedule.rb +335 -0
  201. data/test/types/service.rb +137 -21
  202. data/test/types/sshkey.rb +140 -0
  203. data/test/types/symlink.rb +3 -5
  204. data/test/types/tidy.rb +5 -14
  205. data/test/types/type.rb +67 -11
  206. data/test/types/user.rb +25 -23
  207. metadata +186 -122
  208. data/lib/puppet/type/pfile/create.rb +0 -108
  209. data/lib/puppet/type/pprocess.rb +0 -97
  210. data/lib/puppet/type/typegen.rb +0 -149
  211. data/lib/puppet/type/typegen/filerecord.rb +0 -243
  212. data/lib/puppet/type/typegen/filetype.rb +0 -316
  213. 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