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
data/lib/puppet/daemon.rb CHANGED
@@ -6,8 +6,13 @@ module Puppet
6
6
  # A module that handles operations common to all daemons. This is included
7
7
  # into the Server and Client base classes.
8
8
  module Daemon
9
+ include Puppet::Util
10
+
11
+ Puppet.config.setdefaults(:puppet, :setpidfile => [true,
12
+ "Whether to store a PID file for the daemon."])
9
13
  def daemonname
10
- $0.sub(/.+#{File::SEPARATOR}/,'')
14
+ #$0.sub(/.+#{File::SEPARATOR}/,'')
15
+ Puppet.name
11
16
  end
12
17
 
13
18
  # The path to the pid file for this server
@@ -22,8 +27,6 @@ module Puppet
22
27
  exit(0)
23
28
  end
24
29
 
25
- setpidfile()
26
-
27
30
  # Get rid of console logging
28
31
  Puppet::Log.close(:console)
29
32
 
@@ -36,9 +39,9 @@ module Puppet
36
39
  Puppet::Log.reopen
37
40
  rescue => detail
38
41
  File.open("/tmp/daemonout", "w") { |f|
39
- f.puts "Could not start %s: %s" % [$0, detail]
42
+ f.puts "Could not start %s: %s" % [Puppet.name, detail]
40
43
  }
41
- Puppet.err "Could not start %s: %s" % [$0, detail]
44
+ Puppet.err "Could not start %s: %s" % [Puppet.name, detail]
42
45
  exit(12)
43
46
  end
44
47
  end
@@ -89,6 +92,10 @@ module Puppet
89
92
  return true
90
93
  end
91
94
 
95
+ unless defined? @fqdn
96
+ self.fqdn
97
+ end
98
+
92
99
  # we are not going to encrypt our key, but we need at a minimum
93
100
  # a keyfile and a certfile
94
101
  @certfile = File.join(Puppet[:certdir], [@fqdn, "pem"].join("."))
@@ -120,6 +127,10 @@ module Puppet
120
127
  # of creating the cert request, contacting the remote system, and
121
128
  # storing the cert locally.
122
129
  def requestcert
130
+ unless @secureinit
131
+ raise Puppet::DevError,
132
+ "Tried to request cert without initialized security"
133
+ end
123
134
  retrieved = false
124
135
  Puppet.config.use(:puppet, :certificates)
125
136
  # create the directories involved
@@ -193,53 +204,64 @@ module Puppet
193
204
  return retrieved
194
205
  end
195
206
 
196
- # Create the pid file.
197
- def setpidfile
198
- Puppet.config.use(:puppet)
199
- @pidfile = self.pidfile
200
- if FileTest.exists?(@pidfile)
201
- Puppet.info "Deleting old pid file"
202
- begin
203
- File.unlink(@pidfile)
204
- rescue Errno::EACCES
205
- Puppet.err "Could not delete old PID file; cannot create new one"
206
- return
207
+ # Remove the pid file
208
+ def rmpidfile
209
+ threadlock(:pidfile) do
210
+ if defined? @pidfile and @pidfile and FileTest.exists?(@pidfile)
211
+ begin
212
+ File.unlink(@pidfile)
213
+ rescue => detail
214
+ Puppet.err "Could not remove PID file %s: %s" %
215
+ [@pidfile, detail]
216
+ end
207
217
  end
208
218
  end
219
+ end
209
220
 
210
- #unless FileTest.exists?(Puppet[:rundir])
211
- # Puppet.recmkdir(Puppet[:rundir])
212
- # File.chmod(01777, Puppet[:rundir])
213
- #end
221
+ # Create the pid file.
222
+ def setpidfile
223
+ return unless Puppet[:setpidfile]
224
+ threadlock(:pidfile) do
225
+ Puppet.config.use(:puppet)
226
+ @pidfile = self.pidfile
227
+ if FileTest.exists?(@pidfile)
228
+ if defined? $setpidfile
229
+ return
230
+ else
231
+ raise Puppet::Error, "A PID file already exists for #{Puppet.name}
232
+ at #{@pidfile}. Not starting."
233
+ end
234
+ end
214
235
 
215
- Puppet.info "Setting pidfile to %s" % @pidfile
216
- begin
217
- File.open(@pidfile, "w") { |f| f.puts $$ }
218
- rescue => detail
219
- Puppet.err "Could not create PID file: %s" % detail
220
- exit(74)
236
+ Puppet.info "Creating PID file to %s" % @pidfile
237
+ begin
238
+ File.open(@pidfile, "w") { |f| f.puts $$ }
239
+ rescue => detail
240
+ Puppet.err "Could not create PID file: %s" % detail
241
+ exit(74)
242
+ end
243
+ $setpidfile = true
221
244
  end
222
- Puppet.info "pid file is %s" % @pidfile
223
245
  end
224
246
 
225
247
  # Shut down our server
226
248
  def shutdown
227
249
  # Remove our pid file
228
- if defined? @pidfile and @pidfile and FileTest.exists?(@pidfile)
229
- begin
230
- File.unlink(@pidfile)
231
- rescue => detail
232
- Puppet.err "Could not remove PID file %s: %s" %
233
- [@pidfile, detail]
234
- end
250
+ rmpidfile()
251
+
252
+ # And close all logs except the console.
253
+ Puppet::Log.destinations.reject { |d| d == :console }.each do |dest|
254
+ Puppet::Log.close(dest)
235
255
  end
236
256
 
237
- # And close all logs
238
- Puppet::Log.close
257
+ super
258
+ end
239
259
 
260
+ def start
261
+ setpidfile()
240
262
  super
241
263
  end
242
264
  end
243
265
  end
244
266
 
245
- # $Id: daemon.rb 965 2006-03-02 07:30:14Z luke $
267
+ # $Id: daemon.rb 1315 2006-06-27 05:15:51Z luke $
@@ -6,6 +6,7 @@ require 'puppet'
6
6
  # and provides a few simple across-the-board functions like 'noop'
7
7
  class Puppet::Element
8
8
  include Puppet
9
+ include Puppet::Util
9
10
  attr_writer :noop
10
11
 
11
12
  class << self
@@ -66,4 +67,4 @@ class Puppet::Element
66
67
 
67
68
  end
68
69
 
69
- # $Id: element.rb 980 2006-03-03 23:06:40Z luke $
70
+ # $Id: element.rb 1227 2006-05-28 22:13:46Z luke $
data/lib/puppet/event.rb CHANGED
@@ -75,6 +75,17 @@ module Puppet
75
75
  @subscriptions[stype][sname] << sub
76
76
  end
77
77
 
78
+ # Collect all of the subscriptions that target a specific event.
79
+ def self.targets_of(event, source)
80
+ type, name = self.split(source)
81
+
82
+ @subscriptions[type][name].each { |sub|
83
+ if sub.match?(event)
84
+ yield sub
85
+ end
86
+ }
87
+ end
88
+
78
89
  # Trigger the subscriptions related to an event, and then pass it up
79
90
  # as appropriate
80
91
  def self.trigger(source, event)
@@ -195,7 +206,7 @@ module Puppet
195
206
  end
196
207
 
197
208
  # Trigger a subscription, which basically calls the associated method
198
- # on the target object.
209
+ # on the target object. XXX This is currently unused.
199
210
  def trigger(transaction)
200
211
  event = nil
201
212
 
@@ -245,9 +256,9 @@ module Puppet
245
256
  end
246
257
 
247
258
  def to_s
248
- self.event.to_s
259
+ @source.to_s + " -> " + self.event.to_s
249
260
  end
250
261
  end
251
262
  end
252
263
 
253
- # $Id: event.rb 998 2006-03-09 20:46:55Z luke $
264
+ # $Id: event.rb 1178 2006-05-05 19:43:23Z luke $
@@ -112,43 +112,38 @@ module Puppet
112
112
 
113
113
  # Operate on plain files.
114
114
  newfiletype(:ram) do
115
+ @@tabs = {}
116
+
117
+ def self.clear
118
+ @@tabs.clear
119
+ end
120
+
115
121
  def initialize(path)
116
122
  super
117
- @text = ""
123
+ @@tabs[@path] ||= ""
118
124
  end
119
125
 
120
126
  # Read the file.
121
127
  def read
122
128
  Puppet.info "Reading %s from RAM" % @path
123
- @text
129
+ @@tabs[@path]
124
130
  end
125
131
 
126
132
  # Remove the file.
127
133
  def remove
128
134
  Puppet.info "Removing %s from RAM" % @path
129
- @text = ""
135
+ @@tabs[@path] = ""
130
136
  end
131
137
 
132
138
  # Overwrite the file.
133
139
  def write(text)
134
140
  Puppet.info "Writing %s to RAM" % @path
135
- @text = text
141
+ @@tabs[@path] = text
136
142
  end
137
143
  end
138
144
 
139
145
  # Handle Linux-style cron tabs.
140
146
  newfiletype(:crontab) do
141
- # Only add the -u flag when the @path is different. Fedora apparently
142
- # does not think I should be allowed to set the @path to my
143
- def cmdbase
144
- cmd = nil
145
- if @path == Process.uid
146
- return "crontab"
147
- else
148
- return "crontab -u #{@path}"
149
- end
150
- end
151
-
152
147
  def initialize(user)
153
148
  begin
154
149
  uid = Puppet::Util.uid(user)
@@ -178,6 +173,19 @@ module Puppet
178
173
  p.print text
179
174
  }
180
175
  end
176
+
177
+ private
178
+
179
+ # Only add the -u flag when the @path is different. Fedora apparently
180
+ # does not think I should be allowed to set the @path to my
181
+ def cmdbase
182
+ cmd = nil
183
+ if @path == Process.uid
184
+ return "crontab"
185
+ else
186
+ return "crontab -u #{@path}"
187
+ end
188
+ end
181
189
  end
182
190
 
183
191
  # SunOS has completely different cron commands; this class implements
@@ -208,7 +216,8 @@ module Puppet
208
216
  end
209
217
  end
210
218
 
211
- # Treat netinfo tables as a single file, just for simplicity of certain types
219
+ # Treat netinfo tables as a single file, just for simplicity of certain
220
+ # types
212
221
  newfiletype(:netinfo) do
213
222
  class << self
214
223
  attr_accessor :format
@@ -230,8 +239,8 @@ module Puppet
230
239
  end
231
240
  end
232
241
 
233
- # Convert our table to an array of hashes. This only works for handling one
234
- # table at a time.
242
+ # Convert our table to an array of hashes. This only works for
243
+ # handling one table at a time.
235
244
  def to_array(text = nil)
236
245
  unless text
237
246
  text = read
@@ -296,4 +305,4 @@ module Puppet
296
305
  end
297
306
  end
298
307
 
299
- # $Id: filetype.rb 1125 2006-04-20 19:38:48Z luke $
308
+ # $Id: filetype.rb 1402 2006-07-18 15:35:15Z luke $
data/lib/puppet/log.rb CHANGED
@@ -16,21 +16,83 @@ module Puppet
16
16
  @levels = [:debug,:info,:notice,:warning,:err,:alert,:emerg,:crit]
17
17
  @loglevel = 2
18
18
 
19
- @colors = {
20
- :debug => SLATE,
21
- :info => GREEN,
22
- :notice => PINK,
23
- :warning => ORANGE,
24
- :err => YELLOW,
25
- :alert => BLUE,
26
- :emerg => RESET,
27
- :crit => RESET
28
- }
29
-
30
- #@destinations = {:syslog => Syslog.open("puppet")}
31
- #@destinations = {:console => :console}
19
+ @desttypes = {}
20
+
21
+ # A type of log destination.
22
+ class Destination
23
+ class << self
24
+ attr_accessor :name
25
+ end
26
+
27
+ # Mark the things we're supposed to match.
28
+ def self.match(obj)
29
+ @matches ||= []
30
+ @matches << obj
31
+ end
32
+
33
+ # See whether we match a given thing.
34
+ def self.match?(obj)
35
+ # Convert single-word strings into symbols like :console and :syslog
36
+ if obj.is_a? String and obj =~ /^\w+$/
37
+ obj = obj.downcase.intern
38
+ end
39
+
40
+ @matches.each do |thing|
41
+ # Search for direct matches or class matches
42
+ return true if thing === obj or thing == obj.class.to_s
43
+ end
44
+ return false
45
+ end
46
+
47
+ def name
48
+ if defined? @name
49
+ return @name
50
+ else
51
+ return self.class.name
52
+ end
53
+ end
54
+
55
+ # Set how to handle a message.
56
+ def self.sethandler(&block)
57
+ define_method(:handle, &block)
58
+ end
59
+
60
+ # Mark how to initialize our object.
61
+ def self.setinit(&block)
62
+ define_method(:initialize, &block)
63
+ end
64
+ end
65
+
66
+ # Create a new destination type.
67
+ def self.newdesttype(name, options = {}, &block)
68
+ dest = Class.new(Destination)
69
+ name = name.to_s.downcase.intern
70
+ dest.name = name
71
+ dest.match(dest.name)
72
+
73
+ const_set("Dest" + name.to_s.capitalize, dest)
74
+
75
+ @desttypes[dest.name] = dest
76
+
77
+ options.each do |option, value|
78
+ begin
79
+ dest.send(option.to_s + "=", value)
80
+ rescue NoMethodError
81
+ raise "%s is an invalid option for log destinations" % option
82
+ end
83
+ end
84
+
85
+ dest.class_eval(&block)
86
+
87
+ return dest
88
+ end
89
+
32
90
  @destinations = {}
33
91
 
92
+ class << self
93
+ include Puppet::Util
94
+ end
95
+
34
96
  # Reset all logs to basics. Basically just closes all files and undefs
35
97
  # all of the other objects.
36
98
  def Log.close(dest = nil)
@@ -42,7 +104,7 @@ module Puppet
42
104
  @destinations.delete(dest)
43
105
  end
44
106
  else
45
- @destinations.each { |type, dest|
107
+ @destinations.each { |name, dest|
46
108
  if dest.respond_to?(:flush)
47
109
  dest.flush
48
110
  end
@@ -52,8 +114,6 @@ module Puppet
52
114
  }
53
115
  @destinations = {}
54
116
  end
55
-
56
- Puppet.info "closed"
57
117
  end
58
118
 
59
119
  # Flush any log destinations that support such operations.
@@ -112,63 +172,220 @@ module Puppet
112
172
  @levels.dup
113
173
  end
114
174
 
115
- # Create a new log destination.
116
- def Log.newdestination(dest)
117
- # Each destination can only occur once.
118
- if @destinations.include?(dest)
119
- return
175
+ newdesttype :syslog do
176
+ def close
177
+ Syslog.close
120
178
  end
121
179
 
122
- case dest
123
- when "syslog", :syslog
180
+ def initialize
124
181
  if Syslog.opened?
125
182
  Syslog.close
126
183
  end
127
184
  name = Puppet.name
128
185
  name = "puppet-#{name}" unless name =~ /puppet/
129
- @destinations[:syslog] = Syslog.open(name)
130
- when /^\// # files
131
- Puppet.info "opening %s as a log" % dest
186
+
187
+ options = Syslog::LOG_PID | Syslog::LOG_NDELAY
188
+
189
+ # XXX This should really be configurable.
190
+ facility = Syslog::LOG_DAEMON
191
+
192
+ @syslog = Syslog.open(name, options, facility)
193
+ end
194
+
195
+ def handle(msg)
196
+ # XXX Syslog currently has a bug that makes it so you
197
+ # cannot log a message with a '%' in it. So, we get rid
198
+ # of them.
199
+ if msg.source == "Puppet"
200
+ @syslog.send(msg.level, msg.to_s.gsub("%", '%%'))
201
+ else
202
+ @syslog.send(msg.level, "(%s) %s" %
203
+ [msg.source.to_s.gsub("%", ""),
204
+ msg.to_s.gsub("%", '%%')
205
+ ]
206
+ )
207
+ end
208
+ end
209
+ end
210
+
211
+ newdesttype :file do
212
+ match(/^\//)
213
+
214
+ def close
215
+ if defined? @file
216
+ @file.close
217
+ @file = nil
218
+ end
219
+ end
220
+
221
+ def flush
222
+ if defined? @file
223
+ @file.flush
224
+ end
225
+ end
226
+
227
+ def initialize(path)
228
+ @name = path
132
229
  # first make sure the directory exists
133
230
  # We can't just use 'Config.use' here, because they've
134
231
  # specified a "special" destination.
135
- unless FileTest.exist?(File.dirname(dest))
232
+ unless FileTest.exist?(File.dirname(path))
233
+ Puppet.recmkdir(File.dirname(path))
234
+ Puppet.info "Creating log directory %s" % File.dirname(path)
235
+ end
236
+
237
+ # create the log file, if it doesn't already exist
238
+ file = File.open(path, File::WRONLY|File::CREAT|File::APPEND)
239
+
240
+ @file = file
241
+ end
242
+
243
+ def handle(msg)
244
+ @file.puts("%s %s (%s): %s" %
245
+ [msg.time, msg.source, msg.level, msg.to_s])
246
+ end
247
+ end
248
+
249
+ newdesttype :console do
250
+ @@colors = {
251
+ :debug => SLATE,
252
+ :info => GREEN,
253
+ :notice => PINK,
254
+ :warning => ORANGE,
255
+ :err => YELLOW,
256
+ :alert => BLUE,
257
+ :emerg => RESET,
258
+ :crit => RESET
259
+ }
260
+
261
+ def initialize
262
+ # Flush output immediately.
263
+ $stdout.sync = true
264
+ end
265
+
266
+ def handle(msg)
267
+ color = ""
268
+ reset = ""
269
+ if Puppet[:color]
270
+ color = @@colors[msg.level]
271
+ reset = RESET
272
+ end
273
+ if msg.source == "Puppet"
274
+ puts color + "%s: %s" % [
275
+ msg.level, msg.to_s
276
+ ] + reset
277
+ else
278
+ puts color + "%s: %s: %s" % [
279
+ msg.level, msg.source, msg.to_s
280
+ ] + reset
281
+ end
282
+ end
283
+ end
284
+
285
+ newdesttype :host do
286
+ def initialize(host)
287
+ Puppet.info "Treating %s as a hostname" % host
288
+ args = {}
289
+ if host =~ /:(\d+)/
290
+ args[:Port] = $1
291
+ args[:Server] = host.sub(/:\d+/, '')
292
+ else
293
+ args[:Server] = host
294
+ end
295
+
296
+ @name = host
297
+
298
+ @driver = Puppet::Client::LogClient.new(args)
299
+ end
300
+
301
+ def handle(msg)
302
+ unless msg.is_a?(String) or msg.remote
303
+ unless defined? @hostname
304
+ @hostname = Facter["hostname"].value
305
+ end
306
+ unless defined? @domain
307
+ @domain = Facter["domain"].value
308
+ if @domain
309
+ @hostname += "." + @domain
310
+ end
311
+ end
312
+ if msg.source =~ /^\//
313
+ msg.source = @hostname + ":" + msg.source
314
+ elsif msg.source == "Puppet"
315
+ msg.source = @hostname + " " + msg.source
316
+ else
317
+ msg.source = @hostname + " " + msg.source
318
+ end
136
319
  begin
137
- Puppet.recmkdir(File.dirname(dest))
138
- Puppet.info "Creating log directory %s" %
139
- File.dirname(dest)
320
+ #puts "would have sent %s" % msg
321
+ #puts "would have sent %s" %
322
+ # CGI.escape(YAML.dump(msg))
323
+ begin
324
+ tmp = CGI.escape(YAML.dump(msg))
325
+ rescue => detail
326
+ puts "Could not dump: %s" % detail.to_s
327
+ return
328
+ end
329
+ # Add the hostname to the source
330
+ @driver.addlog(tmp)
140
331
  rescue => detail
141
- Log.destination = :console
142
- Puppet.err "Could not create log directory: %s" %
143
- detail
144
- return
332
+ if Puppet[:debug]
333
+ puts detail.backtrace
334
+ end
335
+ Puppet.err detail
336
+ Puppet::Log.close(self)
145
337
  end
146
338
  end
339
+ end
340
+ end
147
341
 
148
- begin
149
- # create the log file, if it doesn't already exist
150
- file = File.open(dest,File::WRONLY|File::CREAT|File::APPEND)
151
- rescue => detail
152
- Log.destination = :console
153
- Puppet.err "Could not create log file: %s" %
154
- detail
155
- return
342
+ # Log to a transaction report.
343
+ newdesttype :report do
344
+ match "Puppet::Transaction::Report"
345
+
346
+ def initialize(report)
347
+ @report = report
348
+ end
349
+
350
+ def handle(msg)
351
+ # Only add messages from objects, since anything else is
352
+ # probably unrelated to this run.
353
+ if msg.objectsource?
354
+ @report.newlog(msg)
156
355
  end
157
- @destinations[dest] = file
158
- when "console", :console
159
- @destinations[:console] = :console
160
- when Puppet::Server::Logger
161
- @destinations[dest] = dest
162
- else
163
- Puppet.info "Treating %s as a hostname" % dest
164
- args = {}
165
- if dest =~ /:(\d+)/
166
- args[:Port] = $1
167
- args[:Server] = dest.sub(/:\d+/, '')
356
+ end
357
+ end
358
+
359
+ # Create a new log destination.
360
+ def Log.newdestination(dest)
361
+ # Each destination can only occur once.
362
+ if @destinations.find { |name, obj| obj.name == dest }
363
+ return
364
+ end
365
+
366
+ name, type = @desttypes.find do |name, klass|
367
+ klass.match?(dest)
368
+ end
369
+
370
+ unless type
371
+ raise Puppet::DevError, "Unknown destination type %s" % dest
372
+ end
373
+
374
+ begin
375
+ if type.instance_method(:initialize).arity == 1
376
+ @destinations[dest] = type.new(dest)
168
377
  else
169
- args[:Server] = dest
378
+ @destinations[dest] = type.new()
379
+ end
380
+ rescue => detail
381
+ if Puppet[:debug]
382
+ puts detail.backtrace
383
+ end
384
+
385
+ # If this was our only destination, then add the console back in.
386
+ if @destinations.empty? and (dest != :console and dest != "console")
387
+ newdestination(:console)
170
388
  end
171
- @destinations[dest] = Puppet::Client::LogClient.new(args)
172
389
  end
173
390
  end
174
391
 
@@ -181,83 +398,12 @@ module Puppet
181
398
  if @levels.index(msg.level) < @loglevel
182
399
  return
183
400
  end
184
- @destinations.each { |type, dest|
185
- case dest
186
- when Module # This is the Syslog module
187
- next if msg.remote
188
- # XXX Syslog currently has a bug that makes it so you
189
- # cannot log a message with a '%' in it. So, we get rid
190
- # of them.
191
- if msg.source == "Puppet"
192
- dest.send(msg.level, msg.to_s.gsub("%", '%%'))
193
- else
194
- dest.send(msg.level, "(%s) %s" %
195
- [msg.source.to_s.gsub("%", ""),
196
- msg.to_s.gsub("%", '%%')
197
- ]
198
- )
199
- end
200
- when File:
201
- dest.puts("%s %s (%s): %s" %
202
- [msg.time, msg.source, msg.level, msg.to_s])
203
- when :console
204
- color = ""
205
- reset = ""
206
- if Puppet[:color]
207
- color = @colors[msg.level]
208
- reset = RESET
209
- end
210
- if msg.source == "Puppet"
211
- puts color + "%s: %s" % [
212
- msg.level, msg.to_s
213
- ] + reset
214
- else
215
- puts color + "%s: %s: %s" % [
216
- msg.level, msg.source, msg.to_s
217
- ] + reset
218
- end
219
- when Puppet::Client::LogClient
220
- unless msg.is_a?(String) or msg.remote
221
- unless defined? @hostname
222
- @hostname = Facter["hostname"].value
223
- end
224
- unless defined? @domain
225
- @domain = Facter["domain"].value
226
- if @domain
227
- @hostname += "." + @domain
228
- end
229
- end
230
- if msg.source =~ /^\//
231
- msg.source = @hostname + ":" + msg.source
232
- elsif msg.source == "Puppet"
233
- msg.source = @hostname + " " + msg.source
234
- else
235
- msg.source = @hostname + " " + msg.source
236
- end
237
- begin
238
- #puts "would have sent %s" % msg
239
- #puts "would have sent %s" %
240
- # CGI.escape(YAML.dump(msg))
241
- begin
242
- tmp = CGI.escape(YAML.dump(msg))
243
- rescue => detail
244
- puts "Could not dump: %s" % detail.to_s
245
- return
246
- end
247
- # Add the hostname to the source
248
- dest.addlog(tmp)
249
- #dest.addlog(msg.to_s)
250
- sleep(0.5)
251
- rescue => detail
252
- Puppet.err detail
253
- @destinations.delete(type)
254
- end
255
- end
256
- else
257
- raise Puppet::Error, "Invalid log destination %s" % dest
258
- #puts "Invalid log destination %s" % dest.inspect
401
+
402
+ @destinations.each do |name, dest|
403
+ threadlock(dest) do
404
+ dest.handle(msg)
259
405
  end
260
- }
406
+ end
261
407
  end
262
408
 
263
409
  def Log.sendlevel?(level)
@@ -332,6 +478,15 @@ module Puppet
332
478
  Log.newmessage(self)
333
479
  end
334
480
 
481
+ # Was the source of this log an object?
482
+ def objectsource?
483
+ if defined? @objectsource and @objectsource
484
+ @objectsource
485
+ else
486
+ false
487
+ end
488
+ end
489
+
335
490
  # If they pass a source in to us, we make sure it is a string, and
336
491
  # we retrieve any tags we can.
337
492
  def source=(source)
@@ -339,8 +494,10 @@ module Puppet
339
494
  # is a bit of a stupid hack, specifically testing for elements, but
340
495
  # eh.
341
496
  if source.is_a?(Puppet::Element) and source.respond_to?(:path)
497
+ @objectsource = true
342
498
  @source = source.path
343
499
  else
500
+ @objectsource = false
344
501
  @source = source.to_s
345
502
  end
346
503
  unless defined? @tags and @tags
@@ -350,10 +507,18 @@ module Puppet
350
507
  end
351
508
  end
352
509
 
510
+ def tagged?(tag)
511
+ @tags.include?(tag)
512
+ end
513
+
514
+ def to_report
515
+ "%s %s (%s): %s" % [self.time, self.source, self.level, self.to_s]
516
+ end
517
+
353
518
  def to_s
354
519
  return @message
355
520
  end
356
521
  end
357
522
  end
358
523
 
359
- # $Id: log.rb 1124 2006-04-20 07:00:10Z luke $
524
+ # $Id: log.rb 1422 2006-07-22 03:32:56Z luke $