puppet 0.16.0 → 0.18.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (185) hide show
  1. data/CHANGELOG +98 -0
  2. data/Rakefile +5 -1
  3. data/bin/puppet +1 -1
  4. data/bin/puppetca +25 -11
  5. data/bin/puppetd +189 -66
  6. data/bin/puppetdoc +79 -62
  7. data/bin/puppetmasterd +93 -49
  8. data/bin/puppetrun +385 -0
  9. data/conf/redhat/client.init +5 -2
  10. data/conf/redhat/fileserver.conf +1 -1
  11. data/conf/redhat/lsb-config.patch +51 -0
  12. data/conf/redhat/puppet.spec +45 -18
  13. data/conf/redhat/puppetd.conf +32 -4
  14. data/conf/redhat/server.init +5 -2
  15. data/conf/solaris/pkginfo +7 -0
  16. data/conf/solaris/smf/puppetd.xml +77 -0
  17. data/conf/solaris/smf/puppetmasterd.xml +77 -0
  18. data/conf/solaris/smf/svc-puppetd +66 -0
  19. data/conf/solaris/smf/svc-puppetmasterd +62 -0
  20. data/examples/code/failers/noobjectrvalue +1 -0
  21. data/examples/code/snippets/deepclassheirarchy.pp +23 -0
  22. data/examples/code/snippets/defineoverrides.pp +17 -0
  23. data/examples/code/snippets/emptyexec.pp +3 -0
  24. data/examples/code/snippets/selectorvalues.pp +6 -1
  25. data/examples/code/snippets/tagged.pp +35 -0
  26. data/ext/ldap/puppet.schema +2 -2
  27. data/install.rb +4 -2
  28. data/lib/puppet.rb +206 -15
  29. data/lib/puppet/client.rb +30 -20
  30. data/lib/puppet/client/ca.rb +2 -2
  31. data/lib/puppet/client/dipper.rb +5 -9
  32. data/lib/puppet/client/master.rb +224 -44
  33. data/lib/puppet/client/pelement.rb +54 -9
  34. data/lib/puppet/client/proxy.rb +3 -2
  35. data/lib/puppet/client/reporter.rb +34 -0
  36. data/lib/puppet/client/runner.rb +17 -0
  37. data/lib/puppet/config.rb +136 -55
  38. data/lib/puppet/daemon.rb +59 -37
  39. data/lib/puppet/element.rb +2 -1
  40. data/lib/puppet/event.rb +14 -3
  41. data/lib/puppet/filetype.rb +28 -19
  42. data/lib/puppet/log.rb +297 -132
  43. data/lib/puppet/metric.rb +31 -131
  44. data/lib/puppet/networkclient.rb +73 -46
  45. data/lib/puppet/parameter.rb +49 -1
  46. data/lib/puppet/parsedfile.rb +32 -12
  47. data/lib/puppet/parser/ast.rb +6 -1
  48. data/lib/puppet/parser/ast/astarray.rb +32 -6
  49. data/lib/puppet/parser/ast/collection.rb +91 -0
  50. data/lib/puppet/parser/ast/compdef.rb +2 -2
  51. data/lib/puppet/parser/ast/component.rb +24 -11
  52. data/lib/puppet/parser/ast/function.rb +50 -0
  53. data/lib/puppet/parser/ast/hostclass.rb +70 -22
  54. data/lib/puppet/parser/ast/node.rb +17 -8
  55. data/lib/puppet/parser/ast/nodedef.rb +1 -1
  56. data/lib/puppet/parser/ast/objectdef.rb +28 -10
  57. data/lib/puppet/parser/ast/selector.rb +4 -1
  58. data/lib/puppet/parser/functions.rb +145 -0
  59. data/lib/puppet/parser/interpreter.rb +243 -86
  60. data/lib/puppet/parser/lexer.rb +5 -4
  61. data/lib/puppet/parser/parser.rb +586 -505
  62. data/lib/puppet/parser/scope.rb +337 -187
  63. data/lib/puppet/rails.rb +115 -0
  64. data/lib/puppet/rails/database.rb +40 -0
  65. data/lib/puppet/rails/host.rb +83 -0
  66. data/lib/puppet/rails/rails_object.rb +42 -0
  67. data/lib/puppet/rails/rails_parameter.rb +5 -0
  68. data/lib/puppet/reports/rrdgraph.rb +20 -0
  69. data/lib/puppet/reports/tagmail.rb +94 -0
  70. data/lib/puppet/server.rb +20 -4
  71. data/lib/puppet/server/authconfig.rb +14 -3
  72. data/lib/puppet/server/authstore.rb +2 -2
  73. data/lib/puppet/server/ca.rb +23 -11
  74. data/lib/puppet/server/filebucket.rb +10 -10
  75. data/lib/puppet/server/fileserver.rb +4 -8
  76. data/lib/puppet/server/master.rb +19 -22
  77. data/lib/puppet/server/pelement.rb +28 -16
  78. data/lib/puppet/server/report.rb +184 -0
  79. data/lib/puppet/server/runner.rb +62 -0
  80. data/lib/puppet/server/servlet.rb +23 -9
  81. data/lib/puppet/sslcertificates/ca.rb +25 -1
  82. data/lib/puppet/statechange.rb +34 -53
  83. data/lib/puppet/storage.rb +1 -2
  84. data/lib/puppet/transaction.rb +305 -133
  85. data/lib/puppet/transaction/report.rb +42 -0
  86. data/lib/puppet/transportable.rb +57 -33
  87. data/lib/puppet/type.rb +260 -127
  88. data/lib/puppet/type/component.rb +9 -21
  89. data/lib/puppet/type/cron.rb +367 -116
  90. data/lib/puppet/type/exec.rb +15 -16
  91. data/lib/puppet/type/group.rb +9 -1
  92. data/lib/puppet/type/nameservice.rb +2 -5
  93. data/lib/puppet/type/nameservice/netinfo.rb +3 -0
  94. data/lib/puppet/type/nameservice/objectadd.rb +23 -10
  95. data/lib/puppet/type/nameservice/pw.rb +16 -3
  96. data/lib/puppet/type/package.rb +25 -75
  97. data/lib/puppet/type/package/apple.rb +15 -1
  98. data/lib/puppet/type/package/apt.rb +37 -2
  99. data/lib/puppet/type/package/blastwave.rb +136 -0
  100. data/lib/puppet/type/package/dpkg.rb +4 -4
  101. data/lib/puppet/type/package/gem.rb +119 -0
  102. data/lib/puppet/type/package/openbsd.rb +7 -6
  103. data/lib/puppet/type/package/ports.rb +7 -2
  104. data/lib/puppet/type/package/rpm.rb +1 -1
  105. data/lib/puppet/type/package/sun.rb +23 -9
  106. data/lib/puppet/type/package/sunfreeware.rb +7 -0
  107. data/lib/puppet/type/package/yum.rb +16 -9
  108. data/lib/puppet/type/parsedtype.rb +7 -5
  109. data/lib/puppet/type/parsedtype/mount.rb +55 -34
  110. data/lib/puppet/type/parsedtype/port.rb +7 -1
  111. data/lib/puppet/type/parsedtype/sshkey.rb +6 -16
  112. data/lib/puppet/type/pfile.rb +115 -23
  113. data/lib/puppet/type/pfile/checksum.rb +18 -5
  114. data/lib/puppet/type/pfile/content.rb +2 -2
  115. data/lib/puppet/type/pfile/ensure.rb +3 -3
  116. data/lib/puppet/type/pfile/group.rb +2 -2
  117. data/lib/puppet/type/pfile/source.rb +28 -17
  118. data/lib/puppet/type/pfile/target.rb +25 -17
  119. data/lib/puppet/type/pfilebucket.rb +25 -6
  120. data/lib/puppet/type/schedule.rb +6 -6
  121. data/lib/puppet/type/service.rb +24 -14
  122. data/lib/puppet/type/service/debian.rb +1 -1
  123. data/lib/puppet/type/service/redhat.rb +13 -10
  124. data/lib/puppet/type/service/smf.rb +3 -3
  125. data/lib/puppet/type/state.rb +1 -2
  126. data/lib/puppet/type/symlink.rb +3 -4
  127. data/lib/puppet/type/user.rb +22 -10
  128. data/lib/puppet/type/yumrepo.rb +6 -1
  129. data/lib/puppet/type/zone.rb +595 -0
  130. data/lib/puppet/util.rb +58 -12
  131. data/test/client/client.rb +2 -2
  132. data/test/client/master.rb +92 -3
  133. data/test/client/pelement.rb +99 -0
  134. data/test/executables/puppetbin.rb +3 -4
  135. data/test/executables/puppetca.rb +3 -3
  136. data/test/executables/puppetd.rb +3 -3
  137. data/test/executables/puppetmasterd.rb +1 -5
  138. data/test/executables/puppetmodule.rb +2 -2
  139. data/test/language/ast.rb +200 -11
  140. data/test/language/functions.rb +245 -0
  141. data/test/language/interpreter.rb +155 -6
  142. data/test/language/lexer.rb +35 -2
  143. data/test/language/node.rb +48 -1
  144. data/test/language/parser.rb +250 -1
  145. data/test/language/rails.rb +105 -0
  146. data/test/language/scope.rb +304 -10
  147. data/test/language/snippets.rb +54 -5
  148. data/test/language/transportable.rb +60 -28
  149. data/test/other/config.rb +214 -1
  150. data/test/other/events.rb +67 -9
  151. data/test/other/log.rb +31 -5
  152. data/test/other/metrics.rb +23 -21
  153. data/test/other/parsedfile.rb +29 -2
  154. data/test/other/puppet.rb +79 -0
  155. data/test/other/report.rb +106 -0
  156. data/test/other/storage.rb +2 -2
  157. data/test/other/transactions.rb +128 -2
  158. data/test/puppet/utiltest.rb +10 -5
  159. data/test/puppettest.rb +193 -21
  160. data/test/server/authstore.rb +13 -4
  161. data/test/server/bucket.rb +33 -8
  162. data/test/server/ca.rb +44 -6
  163. data/test/server/master.rb +6 -7
  164. data/test/server/pelement.rb +15 -5
  165. data/test/server/report.rb +93 -0
  166. data/test/server/runner.rb +107 -0
  167. data/test/server/server.rb +28 -1
  168. data/test/types/cron.rb +339 -31
  169. data/test/types/file.rb +256 -24
  170. data/test/types/filebucket.rb +6 -2
  171. data/test/types/filesources.rb +41 -92
  172. data/test/types/group.rb +31 -1
  173. data/test/types/host.rb +2 -1
  174. data/test/types/mount.rb +18 -1
  175. data/test/types/package.rb +200 -18
  176. data/test/types/service.rb +5 -1
  177. data/test/types/sshkey.rb +2 -1
  178. data/test/types/symlink.rb +3 -2
  179. data/test/types/type.rb +180 -1
  180. data/test/types/user.rb +65 -27
  181. data/test/types/yumrepo.rb +15 -0
  182. data/test/types/zone.rb +437 -0
  183. metadata +43 -4
  184. data/bin/cf2puppet +0 -186
  185. data/conf/redhat/puppetmasterd.conf +0 -5
@@ -3,7 +3,7 @@ class Puppet::Parser::AST
3
3
  # specified node, and this parse tree is only ever looked up when
4
4
  # a client connects.
5
5
  class NodeDef < AST::Branch
6
- attr_accessor :names, :code, :parentclass, :keyword
6
+ attr_accessor :names, :code, :parentclass, :keyword, :scope
7
7
 
8
8
  def each
9
9
  [@names,@code].each { |child| yield child }
@@ -2,7 +2,7 @@ class Puppet::Parser::AST
2
2
  # Any normal puppet object declaration. Can result in a class or a
3
3
  # component, in addition to builtin types.
4
4
  class ObjectDef < AST::Branch
5
- attr_accessor :name, :type
5
+ attr_accessor :name, :type, :collectable
6
6
  attr_reader :params
7
7
 
8
8
  # probably not used at all
@@ -55,23 +55,40 @@ class Puppet::Parser::AST
55
55
  raise error
56
56
  end
57
57
 
58
+ hash = {}
59
+ # Evaluate all of the specified params.
60
+ @params.each { |param|
61
+ ary = param.safeevaluate(:scope => scope)
62
+ hash[ary[0]] = ary[1]
63
+ }
64
+
58
65
  objnames = [nil]
59
- # Autogenerate the name if one was not passed.
66
+ # Determine our name if we have one.
60
67
  if self.name
61
68
  objnames = @name.safeevaluate(:scope => scope)
62
69
  # it's easier to always use an array, even for only one name
63
70
  unless objnames.is_a?(Array)
64
71
  objnames = [objnames]
65
72
  end
66
- end
73
+ else
74
+ # See if they specified the name as a parameter instead of as a
75
+ # normal name (i.e., before the colon).
76
+ unless object # we're a builtin
77
+ if objclass = Puppet::Type.type(objtype)
78
+ namevar = objclass.namevar
67
79
 
68
- hash = {}
80
+ tmp = hash["name"] || hash[namevar.to_s]
69
81
 
70
- # then set all of the specified params
71
- @params.each { |param|
72
- ary = param.safeevaluate(:scope => scope)
73
- hash[ary[0]] = ary[1]
74
- }
82
+ if tmp
83
+ objnames = [tmp]
84
+ end
85
+ else
86
+ # this should never happen, because we've already
87
+ # typechecked, but it's no real problem if it does happen.
88
+ # We just end up with an object with no name.
89
+ end
90
+ end
91
+ end
75
92
 
76
93
  # this is where our implicit iteration takes place;
77
94
  # if someone passed an array as the name, then we act
@@ -91,7 +108,8 @@ class Puppet::Parser::AST
91
108
  :name => objname,
92
109
  :arguments => hash,
93
110
  :file => @file,
94
- :line => @line
111
+ :line => @line,
112
+ :collectable => self.collectable
95
113
  )
96
114
  rescue Puppet::ParseError => except
97
115
  except.line = self.line
@@ -19,7 +19,10 @@ class Puppet::Parser::AST
19
19
 
20
20
  default = nil
21
21
 
22
- @values = [@values] unless @values.instance_of? AST::ASTArray
22
+ #@values = [@values] unless @values.instance_of? AST::ASTArray
23
+ unless @values.instance_of? AST::ASTArray or @values.instance_of? Array
24
+ @values = [@values]
25
+ end
23
26
 
24
27
  # Then look for a match in the options.
25
28
  @values.each { |obj|
@@ -0,0 +1,145 @@
1
+ # Grr
2
+ require 'puppet/parser/scope'
3
+
4
+ module Puppet::Parser
5
+ module Functions
6
+ # A module for managing parser functions. Each specified function
7
+ # becomes an instance method on the Scope class.
8
+
9
+ # Create a new function type.
10
+ def self.newfunction(name, ftype = :statement, &block)
11
+ @functions ||= {}
12
+ name = name.intern if name.is_a? String
13
+
14
+ if @functions.include? name
15
+ raise Puppet::DevError, "Function %s already defined" % name
16
+ end
17
+
18
+ # We want to use a separate, hidden module, because we don't want
19
+ # people to be able to call them directly.
20
+ unless defined? FCollection
21
+ eval("module FCollection; end")
22
+ end
23
+
24
+ unless ftype == :statement or ftype == :rvalue
25
+ raise Puppet::DevError, "Invalid statement type %s" % ftype.inspect
26
+ end
27
+
28
+ fname = "function_" + name.to_s
29
+ Puppet::Parser::Scope.send(:define_method, fname, &block)
30
+
31
+ # Someday we'll support specifying an arity, but for now, nope
32
+ #@functions[name] = {:arity => arity, :type => ftype}
33
+ @functions[name] = {:type => ftype, :name => fname}
34
+ end
35
+
36
+ # Determine if a given name is a function
37
+ def self.function(name)
38
+ name = name.intern if name.is_a? String
39
+
40
+ if @functions.include? name
41
+ return @functions[name][:name]
42
+ else
43
+ return false
44
+ end
45
+ end
46
+
47
+ # Determine if a given function returns a value or not.
48
+ def self.rvalue?(name)
49
+ name = name.intern if name.is_a? String
50
+
51
+ if @functions.include? name
52
+ case @functions[name][:type]
53
+ when :statement: return false
54
+ when :rvalue: return true
55
+ end
56
+ else
57
+ return false
58
+ end
59
+ end
60
+
61
+ # Include the specified classes
62
+ newfunction(:include) do |vals|
63
+ vals.each do |val|
64
+ if objecttype = lookuptype(val)
65
+ # It's a defined type, so set it into the scope so it can
66
+ # be evaluated.
67
+ setobject(
68
+ :type => val,
69
+ :arguments => {}
70
+ )
71
+ else
72
+ raise Puppet::ParseError, "Unknown class %s" % val
73
+ end
74
+ end
75
+ end
76
+
77
+ # Tag the current scope with each passed name
78
+ newfunction(:tag) do |vals|
79
+ vals.each do |val|
80
+ # Some hackery, because the tags are stored by object id
81
+ # for singletonness.
82
+ self.setclass(val.object_id, val)
83
+ end
84
+
85
+ # Also add them as tags
86
+ self.tag(*vals)
87
+ end
88
+
89
+ # Test whether a given tag is set. This functions as a big OR -- if any of the
90
+ # specified tags are unset, we return false.
91
+ newfunction(:tagged, :rvalue) do |vals|
92
+ classlist = self.classlist
93
+
94
+ retval = true
95
+ vals.each do |val|
96
+ unless classlist.include?(val) or self.tags.include?(val)
97
+ retval = false
98
+ break
99
+ end
100
+ end
101
+
102
+ return retval
103
+ end
104
+
105
+ # Test whether a given class or definition is defined
106
+ newfunction(:defined, :rvalue) do |vals|
107
+ retval = true
108
+
109
+ vals.each do |val|
110
+ unless builtintype?(val) or lookuptype(val)
111
+ retval = false
112
+ break
113
+ end
114
+ end
115
+
116
+ return retval
117
+ end
118
+
119
+ newfunction(:fail, :statement) do |vals|
120
+ vals = vals.collect { |s| s.to_s }.join(" ") if vals.is_a? Array
121
+ raise Puppet::ParseError, vals.to_s
122
+ end
123
+
124
+ newfunction(:template, :rvalue) do |vals|
125
+ require 'erb'
126
+
127
+ vals.collect do |file|
128
+ # Use a wrapper, so the template can't get access to the full
129
+ # Scope object.
130
+ debug "Retrieving template %s" % file
131
+ wrapper = Puppet::Parser::Scope::TemplateWrapper.new(self, file)
132
+
133
+ begin
134
+ wrapper.result()
135
+ rescue => detail
136
+ raise Puppet::ParseError,
137
+ "Failed to parse template %s: %s" %
138
+ [file, detail]
139
+ end
140
+ end.join("")
141
+ end
142
+ end
143
+ end
144
+
145
+ # $Id: functions.rb 1383 2006-07-11 16:52:20Z luke $
@@ -15,6 +15,14 @@ module Puppet
15
15
  Puppet.setdefaults("ldap",
16
16
  :ldapnodes => [false,
17
17
  "Whether to search for node configurations in LDAP."],
18
+ :ldapssl => [false,
19
+ "Whether SSL should be used when searching for nodes.
20
+ Defaults to false because SSL usually requires certificates
21
+ to be set up on the client side."],
22
+ :ldaptls => [false,
23
+ "Whether TLS should be used when searching for nodes.
24
+ Defaults to false because TLS usually requires certificates
25
+ to be set up on the client side."],
18
26
  :ldapserver => ["ldap",
19
27
  "The LDAP server. Only used if ``ldapnodes`` is enabled."],
20
28
  :ldapport => [389,
@@ -38,10 +46,41 @@ module Puppet
38
46
  branch under your main directory."]
39
47
  )
40
48
 
41
- attr_accessor :ast, :filetimeout
49
+ Puppet.setdefaults(:puppetmaster,
50
+ :storeconfigs => [false,
51
+ "Whether to store each client's configuration. This
52
+ requires ActiveRecord from Ruby on Rails."]
53
+ )
54
+
55
+ attr_accessor :ast
56
+
57
+ class << self
58
+ attr_writer :ldap
59
+ end
42
60
  # just shorten the constant path a bit, using what amounts to an alias
43
61
  AST = Puppet::Parser::AST
44
62
 
63
+ # Create an ldap connection. This is a class method so others can call
64
+ # it and use the same variables and such.
65
+ def self.ldap
66
+ unless defined? @ldap and @ldap
67
+ if Puppet[:ldapssl]
68
+ @ldap = LDAP::SSLConn.new(Puppet[:ldapserver], Puppet[:ldapport])
69
+ elsif Puppet[:ldaptls]
70
+ @ldap = LDAP::SSLConn.new(
71
+ Puppet[:ldapserver], Puppet[:ldapport], true
72
+ )
73
+ else
74
+ @ldap = LDAP::Conn.new(Puppet[:ldapserver], Puppet[:ldapport])
75
+ end
76
+ @ldap.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
77
+ @ldap.set_option(LDAP::LDAP_OPT_REFERRALS, LDAP::LDAP_OPT_ON)
78
+ @ldap.simple_bind(Puppet[:ldapuser], Puppet[:ldappassword])
79
+ end
80
+
81
+ return @ldap
82
+ end
83
+
45
84
  # create our interpreter
46
85
  def initialize(hash)
47
86
  if @code = hash[:Code]
@@ -49,7 +88,6 @@ module Puppet
49
88
  elsif ! @file = hash[:Manifest]
50
89
  raise Puppet::DevError, "You must provide code or a manifest"
51
90
  end
52
- @filetimeout = hash[:ParseCheck] || 15
53
91
 
54
92
  @lastchecked = 0
55
93
 
@@ -59,19 +97,24 @@ module Puppet
59
97
  @usenodes = true
60
98
  end
61
99
 
62
- @nodesources = hash[:NodeSources] || [:file]
100
+ # By default, we only search the parse tree.
101
+ @nodesources = []
102
+
103
+ if Puppet[:ldapnodes]
104
+ @nodesources << :ldap
105
+ end
63
106
 
64
- @nodesources.each { |source|
65
- method = "setup_%s" % source.to_s
66
- if respond_to? method
67
- begin
68
- self.send(method)
69
- rescue => detail
70
- raise Puppet::Error,
71
- "Could not set up node source %s" % source
107
+ if hash[:NodeSources]
108
+ hash[:NodeSources].each do |src|
109
+ if respond_to? "nodesearch_#{src.to_s}"
110
+ @nodesources << src.to_s.intern
111
+ else
112
+ Puppet.warning "Node source '#{src}' not supported"
72
113
  end
73
114
  end
74
- }
115
+ end
116
+
117
+ @setup = false
75
118
 
76
119
  # Set it to either the value or nil. This is currently only used
77
120
  # by the cfengine module.
@@ -79,40 +122,49 @@ module Puppet
79
122
 
80
123
  @local = hash[:Local] || false
81
124
 
82
- # Create our parser object
83
- parsefiles
84
- end
85
-
86
- # Connect to the LDAP Server
87
- def setup_ldap
88
- begin
89
- require 'ldap'
90
- rescue LoadError
91
- @ldap = nil
92
- return
125
+ if hash.include?(:ForkSave)
126
+ @forksave = hash[:ForkSave]
127
+ else
128
+ # This is just too dangerous right now. Sorry, it's going
129
+ # to have to be slow.
130
+ @forksave = false
93
131
  end
94
- begin
95
- @ldap = LDAP::Conn.new(Puppet[:ldapserver], Puppet[:ldapport])
96
- @ldap.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
97
- @ldap.simple_bind(Puppet[:ldapuser], Puppet[:ldappassword])
98
- rescue => detail
99
- raise Puppet::Error, "Could not connect to LDAP: %s" % detail
132
+
133
+ if Puppet[:storeconfigs]
134
+ Puppet::Rails.init
100
135
  end
136
+
137
+ @files = []
138
+
139
+ # Create our parser object
140
+ parsefiles
101
141
  end
102
142
 
103
- # Search for our node in the various locations.
143
+ # Search for our node in the various locations. This only searches
144
+ # locations external to the files; the scope is responsible for
145
+ # searching the parse tree.
104
146
  def nodesearch(node)
105
147
  # At this point, stop at the first source that defines
106
148
  # the node
107
149
  @nodesources.each do |source|
108
150
  method = "nodesearch_%s" % source
151
+ parent = nil
152
+ nodeclasses = nil
109
153
  if self.respond_to? method
110
154
  parent, nodeclasses = self.send(method, node)
111
- end
112
155
 
113
- if nodeclasses
114
- Puppet.info "Found %s in %s" % [node, source]
115
- return parent, nodeclasses
156
+ if parent or (nodeclasses and !nodeclasses.empty?)
157
+ Puppet.info "Found %s in %s" % [node, source]
158
+ return parent, nodeclasses
159
+ else
160
+ # Look for a default node.
161
+ parent, nodeclasses = self.send(method, "default")
162
+ if parent or (nodeclasses and !nodeclasses.empty?)
163
+ Puppet.info "Found default node for %s in %s" %
164
+ [node, source]
165
+ return parent, nodeclasses
166
+ end
167
+ end
116
168
  end
117
169
  end
118
170
 
@@ -122,8 +174,16 @@ module Puppet
122
174
  # Find the ldap node and extra the info, returning just
123
175
  # the critical data.
124
176
  def nodesearch_ldap(node)
125
- unless defined? @ldap
126
- ldapconnect()
177
+ unless defined? @ldap and @ldap
178
+ setup_ldap()
179
+ unless @ldap
180
+ Puppet.info "Skipping ldap source; no ldap connection"
181
+ return nil, []
182
+ end
183
+ end
184
+
185
+ if node =~ /\./
186
+ node = node.sub(/\..+/, '')
127
187
  end
128
188
 
129
189
  filter = Puppet[:ldapstring]
@@ -146,27 +206,39 @@ module Puppet
146
206
  classes = []
147
207
 
148
208
  found = false
149
- # We're always doing a sub here; oh well.
150
- @ldap.search(Puppet[:ldapbase], 2, filter, sattrs) do |entry|
151
- found = true
152
- if pattr
153
- if values = entry.vals(pattr)
154
- if values.length > 1
155
- raise Puppet::Error,
156
- "Node %s has more than one parent: %s" %
157
- [node, values.inspect]
158
- end
159
- unless values.empty?
160
- parent = values.shift
209
+ count = 0
210
+ begin
211
+ # We're always doing a sub here; oh well.
212
+ @ldap.search(Puppet[:ldapbase], 2, filter, sattrs) do |entry|
213
+ found = true
214
+ if pattr
215
+ if values = entry.vals(pattr)
216
+ if values.length > 1
217
+ raise Puppet::Error,
218
+ "Node %s has more than one parent: %s" %
219
+ [node, values.inspect]
220
+ end
221
+ unless values.empty?
222
+ parent = values.shift
223
+ end
161
224
  end
162
225
  end
163
- end
164
226
 
165
- attrs.each { |attr|
166
- if values = entry.vals(attr)
167
- classes += values
168
- end
169
- }
227
+ attrs.each { |attr|
228
+ if values = entry.vals(attr)
229
+ values.each do |v| classes << v end
230
+ end
231
+ }
232
+ end
233
+ rescue => detail
234
+ if count == 0
235
+ # Try reconnecting to ldap
236
+ @ldap = nil
237
+ setup_ldap()
238
+ retry
239
+ else
240
+ raise Puppet::Error, "LDAP Search failed: %s" % detail
241
+ end
170
242
  end
171
243
 
172
244
  classes.flatten!
@@ -179,8 +251,30 @@ module Puppet
179
251
  @parsedate
180
252
  end
181
253
 
254
+ # Add a new file to check for updateness.
255
+ def newfile(file)
256
+ unless @files.find { |f| f.file == file }
257
+ @files << Puppet::ParsedFile.new(file)
258
+ end
259
+ end
260
+
182
261
  # evaluate our whole tree
183
262
  def run(client, facts)
263
+ # We have to leave this for after initialization because there
264
+ # seems to be a problem keeping ldap open after a fork.
265
+ unless @setup
266
+ @nodesources.each { |source|
267
+ method = "setup_%s" % source.to_s
268
+ if respond_to? method
269
+ begin
270
+ self.send(method)
271
+ rescue => detail
272
+ raise Puppet::Error,
273
+ "Could not set up node source %s" % source
274
+ end
275
+ end
276
+ }
277
+ end
184
278
  parsefiles()
185
279
 
186
280
  # Really, we should stick multiple names in here
@@ -217,10 +311,14 @@ module Puppet
217
311
  args[:classes] += nodeclasses if nodeclasses
218
312
 
219
313
  args[:parentnode] = parent if parent
314
+
315
+ if nodeclasses or parent
316
+ args[:searched] = true
317
+ end
220
318
  end
221
319
 
222
320
  begin
223
- return scope.evaluate(args)
321
+ objects = scope.evaluate(args)
224
322
  rescue Puppet::DevError, Puppet::Error, Puppet::ParseError => except
225
323
  raise
226
324
  rescue => except
@@ -232,6 +330,35 @@ module Puppet
232
330
  #end
233
331
  raise error
234
332
  end
333
+
334
+ if Puppet[:storeconfigs]
335
+ storeconfigs(
336
+ :objects => objects,
337
+ :host => client,
338
+ :facts => facts
339
+ )
340
+ end
341
+
342
+ return objects
343
+ end
344
+
345
+ # Connect to the LDAP Server
346
+ def setup_ldap
347
+ self.class.ldap = nil
348
+ begin
349
+ require 'ldap'
350
+ rescue LoadError
351
+ Puppet.notice(
352
+ "Could not set up LDAP Connection: Missing ruby/ldap libraries"
353
+ )
354
+ @ldap = nil
355
+ return
356
+ end
357
+ begin
358
+ @ldap = self.class.ldap()
359
+ rescue => detail
360
+ raise Puppet::Error, "Could not connect to LDAP: %s" % detail
361
+ end
235
362
  end
236
363
 
237
364
  def scope
@@ -240,37 +367,29 @@ module Puppet
240
367
 
241
368
  private
242
369
 
243
- # Evaluate the configuration. If there aren't any nodes defined, then
244
- # this doesn't actually do anything, because we have to evaluate the
245
- # entire configuration each time we get a connect.
246
- def evaluate
247
- # FIXME When this produces errors, it should specify which
248
- # node caused those errors.
249
- if @usenodes
250
- @scope = Puppet::Parser::Scope.new() # no parent scope
251
- @scope.name = "top"
252
- @scope.type = "puppet"
253
- @scope.interp = self
254
- Puppet.debug "Nodes defined"
255
- @ast.safeevaluate(:scope => @scope)
256
- else
257
- Puppet.debug "No nodes defined"
258
- return
370
+ # Check whether any of our files have changed.
371
+ def checkfiles
372
+ if @files.find { |f| f.changed? }
373
+ @parsedate = Time.now.to_i
259
374
  end
260
375
  end
261
376
 
377
+ # Parse the files, generating our parse tree. This automatically
378
+ # reparses only if files are updated, so it's safe to call multiple
379
+ # times.
262
380
  def parsefiles
381
+ # First check whether there are updates to any non-puppet files
382
+ # like templates. If we need to reparse, this will get quashed,
383
+ # but it needs to be done first in case there's no reparse
384
+ # but there are other file changes.
385
+ checkfiles()
386
+
387
+ # Check if the parser should reparse.
263
388
  if @file
264
389
  if defined? @parser
265
- # Only check the files every 15 seconds or so, not on
266
- # every single connection
267
- if (Time.now - @lastchecked).to_i >= @filetimeout.to_i
268
- unless @parser.reparse?
269
- @lastchecked = Time.now
270
- return false
271
- end
272
- else
273
- return
390
+ unless @parser.reparse?
391
+ @lastchecked = Time.now
392
+ return false
274
393
  end
275
394
  end
276
395
 
@@ -284,6 +403,8 @@ module Puppet
284
403
  end
285
404
 
286
405
  if defined? @parser
406
+ # If this isn't our first time parsing in this process,
407
+ # note that we're reparsing.
287
408
  Puppet.info "Reloading files"
288
409
  end
289
410
  # should i be creating a new parser each time...?
@@ -297,21 +418,57 @@ module Puppet
297
418
  if @local
298
419
  @ast = @parser.parse
299
420
  else
300
- @ast = benchmark(:info, "Parsed manifest") do
301
- @parser.parse
421
+ benchmark(:info, "Parsed manifest") do
422
+ @ast = @parser.parse
302
423
  end
303
424
  end
304
425
 
305
426
  # Mark when we parsed, so we can check freshness
306
427
  @parsedate = Time.now.to_i
307
428
  @lastchecked = Time.now
429
+ end
430
+
431
+ # Store the configs into the database.
432
+ def storeconfigs(hash)
433
+ unless defined? ActiveRecord
434
+ require 'puppet/rails'
435
+ unless defined? ActiveRecord
436
+ raise LoadError,
437
+ "storeconfigs is enabled but rails is unavailable"
438
+ end
439
+ end
440
+
441
+ Puppet::Rails.init
442
+
443
+ # Fork the storage, since we don't need the client waiting
444
+ # on that. How do I avoid this duplication?
445
+ if @forksave
446
+ fork {
447
+ # We store all of the objects, even the collectable ones
448
+ benchmark(:info, "Stored configuration for #{hash[:client]}") do
449
+ # Try to batch things a bit, by putting them into
450
+ # a transaction
451
+ Puppet::Rails::Host.transaction do
452
+ Puppet::Rails::Host.store(hash)
453
+ end
454
+ end
455
+ }
456
+ else
457
+ # We store all of the objects, even the collectable ones
458
+ benchmark(:info, "Stored configuration for #{hash[:client]}") do
459
+ Puppet::Rails::Host.transaction do
460
+ Puppet::Rails::Host.store(hash)
461
+ end
462
+ end
463
+ end
308
464
 
309
- # Reevaluate the config. This is what actually replaces the
310
- # existing scope.
311
- evaluate
465
+ # Now that we've stored everything, we need to strip out
466
+ # the collectable objects so that they are not sent on
467
+ # to the host
468
+ hash[:objects].collectstrip!
312
469
  end
313
470
  end
314
471
  end
315
472
  end
316
473
 
317
- # $Id: interpreter.rb 1103 2006-04-11 17:33:36Z luke $
474
+ # $Id: interpreter.rb 1421 2006-07-21 23:12:51Z luke $