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
@@ -0,0 +1,42 @@
1
+ require 'puppet'
2
+
3
+ # A class for reporting what happens on each client. Reports consist of
4
+ # two types of data: Logs and Metrics. Logs are the output that each
5
+ # change produces, and Metrics are all of the numerical data involved
6
+ # in the transaction.
7
+ class Puppet::Transaction::Report
8
+ attr_accessor :logs, :metrics, :time, :host
9
+
10
+ def initialize
11
+ @metrics = {}
12
+ @logs = []
13
+
14
+ @records = Hash.new do |hash, key|
15
+ hash[key] = []
16
+ end
17
+
18
+ @host = [Facter.value("hostname"), Facter.value("domain")].join(".")
19
+ end
20
+
21
+ # Create a new metric.
22
+ def newmetric(name, hash)
23
+ metric = Puppet::Metric.new(name)
24
+
25
+ hash.each do |name, value|
26
+ metric.newvalue(name, value)
27
+ end
28
+
29
+ @metrics[metric.name] = metric
30
+ end
31
+
32
+ # Add a new log message.
33
+ def newlog(msg)
34
+ @logs << msg
35
+ end
36
+
37
+ def record(metric, object)
38
+ @records[metric] << object
39
+ end
40
+ end
41
+
42
+ # $Id: report.rb 1361 2006-07-04 16:43:16Z luke $
@@ -8,7 +8,7 @@ module Puppet
8
8
  # YAML.
9
9
  class TransObject
10
10
  include Enumerable
11
- attr_accessor :type, :name, :file, :line
11
+ attr_accessor :type, :name, :file, :line, :collectable, :collected
12
12
 
13
13
  attr_writer :tags
14
14
 
@@ -25,8 +25,8 @@ module Puppet
25
25
  def initialize(name,type)
26
26
  @type = type
27
27
  @name = name
28
+ @collectable = false
28
29
  @params = {}
29
- #self.class.add(self)
30
30
  @tags = []
31
31
  end
32
32
 
@@ -54,31 +54,26 @@ module Puppet
54
54
 
55
55
  def to_yaml_properties
56
56
  instance_variables
57
- #%w{ @type @name @file @line @tags }.find_all { |v|
58
- #}
59
57
  end
60
58
 
61
59
  def to_type(parent = nil)
62
60
  retobj = nil
63
- if type = Puppet::Type.type(self.type)
64
- unless retobj = type.create(self)
65
- #Puppet.notice "Could not create %s[%s]" %
66
- # [self.type, self.name]
67
- return nil
61
+ if typeklass = Puppet::Type.type(self.type)
62
+ # FIXME This should really be done differently, but...
63
+ if retobj = typeklass[self.name]
64
+ self.each do |param, val|
65
+ retobj[param] = val
66
+ end
67
+ else
68
+ unless retobj = typeklass.create(self)
69
+ return nil
70
+ end
68
71
  end
69
- #retobj.file = @file
70
- #retobj.line = @line
71
72
  else
72
73
  raise Puppet::Error.new("Could not find object type %s" % self.type)
73
74
  end
74
75
 
75
- #if defined? @tags and @tags
76
- # #Puppet.debug "%s(%s) tags: %s" % [@type, @name, @tags.join(" ")]
77
- # retobj.tags = @tags
78
- #end
79
-
80
76
  if parent
81
- self[:parent] = parent
82
77
  parent.push retobj
83
78
  end
84
79
 
@@ -101,16 +96,52 @@ module Puppet
101
96
  end
102
97
  }
103
98
 
99
+ # Remove all collectable objects from our tree, since the client
100
+ # should not see them.
101
+ def collectstrip!
102
+ @children.dup.each do |child|
103
+ if child.is_a? self.class
104
+ child.collectstrip!
105
+ else
106
+ if child.collectable and ! child.collected
107
+ @children.delete(child)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ # Recursively yield everything.
114
+ def delve(&block)
115
+ @children.each do |obj|
116
+ block.call(obj)
117
+ if obj.is_a? self.class
118
+ obj.delve(&block)
119
+ else
120
+ obj
121
+ end
122
+ end
123
+ end
124
+
104
125
  def each
105
126
  @children.each { |c| yield c }
106
127
  end
107
128
 
129
+ # Turn our heirarchy into a flat list
130
+ def flatten
131
+ @children.collect do |obj|
132
+ if obj.is_a? Puppet::TransBucket
133
+ obj.flatten
134
+ else
135
+ obj
136
+ end
137
+ end.flatten
138
+ end
139
+
108
140
  def initialize
109
141
  @children = []
110
142
  end
111
143
 
112
144
  def push(*args)
113
- #Puppet.warning "calling push"
114
145
  args.each { |arg|
115
146
  case arg
116
147
  when Puppet::TransBucket, Puppet::TransObject
@@ -122,7 +153,6 @@ module Puppet
122
153
  end
123
154
  }
124
155
  @children += args
125
- #Puppet.warning @children.inspect
126
156
  end
127
157
 
128
158
  # Convert to a parseable manifest
@@ -167,15 +197,15 @@ module Puppet
167
197
  usetrans = true
168
198
 
169
199
  if usetrans
170
- name = nil
200
+ tmpname = nil
171
201
 
172
202
  # Nodes have the same name and type
173
203
  if self.name
174
- name = "%s[%s]" % [@type, self.name]
204
+ tmpname = "%s[%s]" % [@type, self.name]
175
205
  else
176
- name = @type
206
+ tmpname = @type
177
207
  end
178
- trans = TransObject.new(name, :component)
208
+ trans = TransObject.new(tmpname, :component)
179
209
  if defined? @parameters
180
210
  @parameters.each { |param,value|
181
211
  Puppet.debug "Defining %s on %s of type %s" %
@@ -186,12 +216,6 @@ module Puppet
186
216
  #Puppet.debug "%s[%s] has no parameters" % [@type, @name]
187
217
  end
188
218
  container = Puppet.type(:component).create(trans)
189
-
190
- if parent
191
- container.parent = parent
192
- #Puppet.warning "parent is of type %s" % parent.class
193
- #trans[:parent] = parent
194
- end
195
219
  else
196
220
  hash = {
197
221
  :name => self.name,
@@ -207,9 +231,9 @@ module Puppet
207
231
  #Puppet.debug "%s[%s] has no parameters" % [@type, @name]
208
232
  end
209
233
 
210
- if parent
211
- hash[:parent] = parent
212
- end
234
+ #if parent
235
+ # hash[:parent] = parent
236
+ #end
213
237
  container = Puppet.type(:component).create(hash)
214
238
  end
215
239
  #Puppet.info container.inspect
@@ -258,4 +282,4 @@ module Puppet
258
282
  #------------------------------------------------------------
259
283
  end
260
284
 
261
- # $Id: transportable.rb 953 2006-02-27 22:25:59Z luke $
285
+ # $Id: transportable.rb 1256 2006-06-13 15:57:06Z luke $
data/lib/puppet/type.rb CHANGED
@@ -21,9 +21,9 @@ class Type < Puppet::Element
21
21
  # In naming methods, I have tried to consistently name the method so
22
22
  # that it is clear whether it operates on all attributes (thus has 'attr' in
23
23
  # the method name, or whether it operates on a specific type of attributes.
24
- attr_accessor :children, :parent
24
+ attr_accessor :children
25
25
  attr_accessor :file, :line
26
- attr_reader :tags
26
+ attr_reader :tags, :parent
27
27
 
28
28
  attr_writer :implicit
29
29
  def implicit?
@@ -36,13 +36,6 @@ class Type < Puppet::Element
36
36
 
37
37
  include Enumerable
38
38
 
39
- # this is currently unused, but I expect to use it for metrics eventually
40
- @@retrieved = Hash.new(0)
41
-
42
- # an array to contain all instances of Type
43
- # also currently unused
44
- @@allobjects = Array.new
45
-
46
39
  # a little fakery, since Puppet itself isn't a type
47
40
  # I don't think this is used any more, now that the language can't
48
41
  # call methods
@@ -64,9 +57,9 @@ class Type < Puppet::Element
64
57
 
65
58
  include Enumerable
66
59
 
67
- def inspect
68
- "Type(%s)" % self.name
69
- end
60
+ #def inspect
61
+ # "Type(%s)" % self.name
62
+ #end
70
63
 
71
64
  # This class is aggregatable, meaning that instances are defined on
72
65
  # one system but instantiated on another
@@ -84,20 +77,6 @@ class Type < Puppet::Element
84
77
  end
85
78
  end
86
79
 
87
- def inspect
88
- str = "Type(%s)" % self.name
89
- if defined? @states
90
- str += " States(" + @states.inspect + ")"
91
- end
92
- if defined? @parameters
93
- str += " Parameters(" + @parameters.inspect + ")"
94
- end
95
- if defined? @metaparams
96
- str += " Metaparams(" + @metaparams.inspect + ")"
97
- end
98
- str
99
- end
100
-
101
80
  # iterate across all of the subclasses of Type
102
81
  def self.eachtype
103
82
  @types.each do |name, type|
@@ -108,6 +87,18 @@ class Type < Puppet::Element
108
87
  end
109
88
  end
110
89
 
90
+ # Create the 'ensure' class. This is a separate method so other types
91
+ # can easily call it and create their own 'ensure' values.
92
+ def self.ensurable(&block)
93
+ if block_given?
94
+ self.newstate(:ensure, Puppet::State::Ensure, &block)
95
+ else
96
+ self.newstate(:ensure, Puppet::State::Ensure) do
97
+ self.defaultvalues
98
+ end
99
+ end
100
+ end
101
+
111
102
  # Should we add the 'ensure' state to this class?
112
103
  def self.ensurable?
113
104
  # If the class has all three of these methods defined, then it's
@@ -122,19 +113,6 @@ class Type < Puppet::Element
122
113
  return ens
123
114
  end
124
115
 
125
- # The work that gets done for every subclass of Type
126
- # this is an implicit method called by Ruby for us
127
- #def self.inherited(sub)
128
- # sub.initvars
129
-
130
- #debug("subtype %s(%s) just created" % [sub,sub.superclass])
131
- # add it to the master list
132
- # unfortunately we can't yet call sub.name, because the #inherited
133
- # method gets called before any commands in the class definition
134
- # get executed, which, um, sucks
135
- #@@typeary.push(sub)
136
- #end
137
-
138
116
  # all of the variables that must be initialized for each subclass
139
117
  def self.initvars
140
118
  # all of the instances of this class
@@ -168,16 +146,56 @@ class Type < Puppet::Element
168
146
 
169
147
  end
170
148
 
149
+ # Do an on-demand plugin load
150
+ def self.loadplugin(name)
151
+ unless Puppet[:pluginpath].split(":").include?(Puppet[:plugindest])
152
+ Puppet.notice "Adding plugin destination %s to plugin search path" %
153
+ Puppet[:plugindest]
154
+ Puppet[:pluginpath] += ":" + Puppet[:plugindest]
155
+ end
156
+ Puppet[:pluginpath].split(":").each do |dir|
157
+ file = ::File.join(dir, name.to_s + ".rb")
158
+ if FileTest.exists?(file)
159
+ begin
160
+ load file
161
+ Puppet.info "loaded %s" % file
162
+ return true
163
+ rescue LoadError => detail
164
+ Puppet.info "Could not load %s: %s" %
165
+ [file, detail]
166
+ return false
167
+ end
168
+ end
169
+ end
170
+ end
171
+
171
172
  # Define a new type.
172
173
  def self.newtype(name, parent = nil, &block)
173
174
  parent ||= Puppet::Type
174
- Puppet::Util.symbolize(name)
175
-
175
+ name = Puppet::Util.symbolize(name)
176
176
 
177
177
  # Create the class, with the correct name.
178
178
  t = Class.new(parent) do
179
179
  @name = name
180
180
  end
181
+
182
+ # Used for method manipulation.
183
+ selfobj = class << self; self; end
184
+
185
+ const = name.to_s.capitalize
186
+ newmethod = "new#{name.to_s}"
187
+
188
+ @types ||= {}
189
+
190
+ if @types.include?(name) and const_defined?(const)
191
+ Puppet.info "Redefining %s" % name
192
+ remove_const(const)
193
+
194
+ if self.respond_to?(newmethod)
195
+ # Remove the old newmethod, too
196
+ selfobj.send(:remove_method,newmethod)
197
+ end
198
+ end
181
199
  const_set(name.to_s.capitalize,t)
182
200
 
183
201
  # Initialize any necessary variables.
@@ -192,22 +210,20 @@ class Type < Puppet::Element
192
210
  t.ensurable
193
211
  end
194
212
 
195
- @types ||= {}
196
-
197
213
  # And add it to our bucket.
198
214
  @types[name] = t
199
- end
200
215
 
201
- # Create the 'ensure' class. This is a separate method so other types
202
- # can easily call it and create their own 'ensure' values.
203
- def self.ensurable(&block)
204
- if block_given?
205
- self.newstate(:ensure, Puppet::State::Ensure, &block)
216
+ # Now define a "new<type>" method for convenience.
217
+ if self.respond_to? newmethod
218
+ # Refuse to overwrite existing methods like 'newparam' or 'newtype'.
219
+ Puppet.warning "'new#{name.to_s}' method already exists; skipping"
206
220
  else
207
- self.newstate(:ensure, Puppet::State::Ensure) do
208
- self.defaultvalues
221
+ selfobj.send(:define_method, newmethod) do |*args|
222
+ t.create(*args)
209
223
  end
210
224
  end
225
+
226
+ t
211
227
  end
212
228
 
213
229
  # Return a Type instance by name.
@@ -224,8 +240,9 @@ class Type < Puppet::Element
224
240
  unless @types.include? name
225
241
  Puppet.warning "Loaded puppet/type/#{name} but no class was created"
226
242
  end
227
- rescue LoadError
228
- # nothing
243
+ rescue LoadError => detail
244
+ # If we can't load it from there, try loading it as a plugin.
245
+ loadplugin(name)
229
246
  end
230
247
  end
231
248
 
@@ -280,25 +297,28 @@ class Type < Puppet::Element
280
297
  raise Puppet::DevError, "must pass a Puppet::Type object"
281
298
  end
282
299
 
283
- if @objects.has_key?(name) and self.isomorphic?
284
- raise Puppet::Error.new(
285
- "Object '%s' of type '%s' already exists with id '%s' vs. '%s'" %
286
- [name, newobj.class.name,
287
- @objects[name].object_id,newobj.object_id]
288
- )
300
+ if exobj = @objects.has_key?(name) and self.isomorphic?
301
+ msg = "Object '%s[%s]' already exists" %
302
+ [name, newobj.class.name]
303
+
304
+ if exobj.file and exobj.line
305
+ msg += ("in file %s at line %s" %
306
+ [object.file, object.line])
307
+ end
308
+ if object.file and object.line
309
+ msg += ("and cannot be redefined in file %s at line %s" %
310
+ [object.file, object.line])
311
+ end
312
+ error = Puppet::Error.new(msg)
289
313
  else
290
314
  #Puppet.info("adding %s of type %s to class list" %
291
315
  # [name,object.class])
292
316
  @objects[name] = newobj
293
317
  end
294
-
295
- # and then add it to the master list
296
- Puppet::Type.push(object)
297
318
  end
298
319
 
299
320
  # remove all type instances; this is mostly only useful for testing
300
321
  def self.allclear
301
- @@allobjects.clear
302
322
  Puppet::Event::Subscription.clear
303
323
  @types.each { |name, type|
304
324
  type.clear
@@ -308,6 +328,9 @@ class Type < Puppet::Element
308
328
  # remove all of the instances of a single type
309
329
  def self.clear
310
330
  if defined? @objects
331
+ @objects.each do |name, obj|
332
+ obj.remove(true)
333
+ end
311
334
  @objects.clear
312
335
  end
313
336
  if defined? @aliases
@@ -317,9 +340,6 @@ class Type < Puppet::Element
317
340
 
318
341
  # remove a specified object
319
342
  def self.delete(object)
320
- if @@allobjects.include?(object)
321
- @@allobjects.delete(object)
322
- end
323
343
  return unless defined? @objects
324
344
  if @objects.include?(object.name)
325
345
  @objects.delete(object.name)
@@ -357,14 +377,6 @@ class Type < Puppet::Element
357
377
  end
358
378
  end
359
379
 
360
- # add an object to the master list of Type instances
361
- # I'm pretty sure this is currently basically unused
362
- def self.push(object)
363
- @@allobjects.push object
364
- #debug("adding %s of type %s to master list" %
365
- # [object.name,object.class])
366
- end
367
-
368
380
  # class and instance methods dealing with parameters and states
369
381
 
370
382
  public
@@ -427,7 +439,7 @@ class Type < Puppet::Element
427
439
  # Create a new metaparam. Requires a block and a name, stores it in the
428
440
  # @parameters array, and does some basic checking on it.
429
441
  def self.newmetaparam(name, &block)
430
- Puppet::Util.symbolize(name)
442
+ name = Puppet::Util.symbolize(name)
431
443
  param = Class.new(Puppet::Parameter) do
432
444
  @name = name
433
445
  end
@@ -453,7 +465,7 @@ class Type < Puppet::Element
453
465
  # Create a new parameter. Requires a block and a name, stores it in the
454
466
  # @parameters array, and does some basic checking on it.
455
467
  def self.newparam(name, &block)
456
- Puppet::Util.symbolize(name)
468
+ name = Puppet::Util.symbolize(name)
457
469
  param = Class.new(Puppet::Parameter) do
458
470
  @name = name
459
471
  end
@@ -778,8 +790,9 @@ class Type < Puppet::Element
778
790
  when :meta
779
791
  self.newmetaparam(self.class.metaparamclass(name), value)
780
792
  when :param
793
+ klass = self.class.attrclass(name)
781
794
  # if they've got a method to handle the parameter, then do it that way
782
- self.newparam(self.class.attrclass(name), value)
795
+ self.newparam(klass, value)
783
796
  else
784
797
  raise Puppet::Error, "Invalid parameter %s" % [name]
785
798
  end
@@ -1011,11 +1024,46 @@ class Type < Puppet::Element
1011
1024
  return @parameters[name].value
1012
1025
  end
1013
1026
 
1027
+ def parent=(parent)
1028
+ if self.parentof?(parent)
1029
+ devfail "%s[%s] is already the parent of %s[%s]" %
1030
+ [self.class.name, self.name, parent.class.name, parent.name]
1031
+ end
1032
+ @parent = parent
1033
+ end
1034
+
1035
+ # Add a hook for testing for recursion.
1036
+ def parentof?(child)
1037
+ if (self == child)
1038
+ debug "parent is equal to child"
1039
+ return true
1040
+ elsif defined? @parent and @parent.parentof?(child)
1041
+ debug "My parent is parent of child"
1042
+ return true
1043
+ elsif @children.include?(child)
1044
+ debug "child is already in children array"
1045
+ return true
1046
+ else
1047
+ return false
1048
+ end
1049
+ end
1050
+
1014
1051
  def push(*childs)
1015
1052
  unless defined? @children
1016
1053
  @children = []
1017
1054
  end
1018
1055
  childs.each { |child|
1056
+ # Make sure we don't have any loops here.
1057
+ if parentof?(child)
1058
+ devfail "Already the parent of %s[%s]" % [child.class.name, child.name]
1059
+ end
1060
+ unless child.is_a?(Puppet::Element)
1061
+ self.debug "Got object of type %s" % child.class
1062
+ self.devfail(
1063
+ "Containers can only contain Puppet::Elements, not %s" %
1064
+ child.class
1065
+ )
1066
+ end
1019
1067
  @children.push(child)
1020
1068
  child.parent = self
1021
1069
  }
@@ -1032,8 +1080,21 @@ class Type < Puppet::Element
1032
1080
  child.remove(rmdeps)
1033
1081
  }
1034
1082
 
1083
+ @children.clear
1084
+
1085
+ # This is hackish (mmm, cut and paste), but it works for now, and it's
1086
+ # better than warnings.
1087
+ [@states, @parameters, @metaparams].each do |hash|
1088
+ hash.each do |name, obj|
1089
+ obj.remove
1090
+ end
1091
+
1092
+ hash.clear
1093
+ end
1094
+
1035
1095
  if rmdeps
1036
1096
  Puppet::Event::Subscription.dependencies(self).each { |dep|
1097
+ #info "Deleting dependency %s" % dep
1037
1098
  #begin
1038
1099
  # self.unsubscribe(dep)
1039
1100
  #rescue
@@ -1042,6 +1103,7 @@ class Type < Puppet::Element
1042
1103
  dep.delete
1043
1104
  }
1044
1105
  Puppet::Event::Subscription.subscribers(self).each { |dep|
1106
+ #info "Unsubscribing from %s" % dep
1045
1107
  begin
1046
1108
  dep.unsubscribe(self)
1047
1109
  rescue
@@ -1053,6 +1115,7 @@ class Type < Puppet::Element
1053
1115
 
1054
1116
  if defined? @parent and @parent
1055
1117
  @parent.delete(self)
1118
+ @parent = nil
1056
1119
  end
1057
1120
  end
1058
1121
 
@@ -1101,7 +1164,6 @@ class Type < Puppet::Element
1101
1164
  # necessary. FIXME This method should be responsible for most of the
1102
1165
  # error handling.
1103
1166
  def self.create(hash)
1104
- #Puppet.warning "Creating %s" % hash.inspect
1105
1167
  # Handle this new object being implicit
1106
1168
  implicit = hash[:implicit] || false
1107
1169
  if hash.include?(:implicit)
@@ -1116,6 +1178,8 @@ class Type < Puppet::Element
1116
1178
  end
1117
1179
  name = hash.name
1118
1180
 
1181
+ #Puppet.debug "Creating %s[%s]" % [self.name, name]
1182
+
1119
1183
  # if the object already exists
1120
1184
  if self.isomorphic? and retobj = self[name]
1121
1185
  # if only one of our objects is implicit, then it's easy to see
@@ -1378,13 +1442,6 @@ class Type < Puppet::Element
1378
1442
  if self.respond_to?(:validate)
1379
1443
  self.validate
1380
1444
  end
1381
-
1382
- # Ensure defaults to present for managed objects, but not otherwise.
1383
- # Because of this complication, we can't use normal defaulting mechanisms
1384
- # if ! @states.include?(:ensure) and self.managed? and
1385
- # self.class.validstate?(:ensure)
1386
- # self[:ensure] = :present
1387
- # end
1388
1445
  end
1389
1446
 
1390
1447
  # Figure out of there are any objects we can automatically add as
@@ -1405,7 +1462,6 @@ class Type < Puppet::Element
1405
1462
  obj = nil
1406
1463
  # Support them passing objects directly, to save some effort.
1407
1464
  if dep.is_a? Puppet::Type
1408
- self.info "requiring %s" % dep.name
1409
1465
  type = dep.class.name
1410
1466
  obj = dep
1411
1467
 
@@ -1418,10 +1474,11 @@ class Type < Puppet::Element
1418
1474
  next
1419
1475
  end
1420
1476
  end
1477
+
1421
1478
  # Skip autorequires that we already require
1422
1479
  next if self.requires?(obj)
1423
- #self.info "Auto-requiring %s %s" % [obj.class.name, obj.name]
1424
1480
 
1481
+ debug "Autorequiring %s %s" % [obj.class.name, obj.name]
1425
1482
  self[:require] = [type, dep]
1426
1483
  }
1427
1484
 
@@ -1779,7 +1836,6 @@ class Type < Puppet::Element
1779
1836
  [self.name,self.class]
1780
1837
  @evalcount = 0
1781
1838
  end
1782
- @@retrieved[self] += 1
1783
1839
  @evalcount += 1
1784
1840
 
1785
1841
  changes = []
@@ -1795,12 +1851,6 @@ class Type < Puppet::Element
1795
1851
  changes += statechanges()
1796
1852
  end
1797
1853
 
1798
- if changes.length > 0
1799
- # add one to the number of out-of-sync instances
1800
- Puppet::Metric.add(self.class,self,:outofsync,1)
1801
- end
1802
- #end
1803
-
1804
1854
  changes << @children.collect { |child|
1805
1855
  ch = child.evaluate
1806
1856
  child.cache(:checked, now)
@@ -1814,7 +1864,6 @@ class Type < Puppet::Element
1814
1864
  changes.flatten!
1815
1865
 
1816
1866
  # now record how many changes we've resulted in
1817
- Puppet::Metric.add(self.class,self,:changes,changes.length)
1818
1867
  if changes.length > 0
1819
1868
  self.debug "%s change(s)" %
1820
1869
  [changes.length]
@@ -1871,12 +1920,20 @@ class Type < Puppet::Element
1871
1920
  def builddepends
1872
1921
  # Handle the requires
1873
1922
  if self[:require]
1874
- self.handledepends(self[:require], :NONE, nil)
1923
+ self.handledepends(self[:require], :NONE, nil, true)
1875
1924
  end
1876
1925
 
1877
1926
  # And the subscriptions
1878
1927
  if self[:subscribe]
1879
- self.handledepends(self[:subscribe], :ALL_EVENTS, :refresh)
1928
+ self.handledepends(self[:subscribe], :ALL_EVENTS, :refresh, true)
1929
+ end
1930
+
1931
+ if self[:notify]
1932
+ self.handledepends(self[:notify], :ALL_EVENTS, :refresh, false)
1933
+ end
1934
+
1935
+ if self[:before]
1936
+ self.handledepends(self[:before], :NONE, nil, false)
1880
1937
  end
1881
1938
  end
1882
1939
 
@@ -1894,7 +1951,7 @@ class Type < Puppet::Element
1894
1951
  }
1895
1952
  end
1896
1953
 
1897
- def handledepends(requires, event, method)
1954
+ def handledepends(requires, event, method, up)
1898
1955
  # Requires are specified in the form of [type, name], so they're always
1899
1956
  # an array. But we want them to be an array of arrays.
1900
1957
  unless requires[0].is_a?(Array)
@@ -1916,22 +1973,26 @@ class Type < Puppet::Element
1916
1973
  end
1917
1974
  self.debug("subscribes to %s" % [object])
1918
1975
 
1919
- #unless @dependencies.include?(object)
1920
- # @dependencies << object
1921
- #end
1922
-
1923
- # pure requires don't call methods
1924
- #next if method.nil?
1976
+ # Are we requiring them, or vice versa?
1977
+ source = target = nil
1978
+ if up
1979
+ source = object
1980
+ target = self
1981
+ else
1982
+ source = self
1983
+ target = object
1984
+ end
1925
1985
 
1926
1986
  # ok, both sides of the connection store some information
1927
1987
  # we store the method to call when a given subscription is
1928
1988
  # triggered, but the source object decides whether
1929
1989
  subargs = {
1930
1990
  :event => event,
1931
- :source => object,
1932
- :target => self
1991
+ :source => source,
1992
+ :target => target
1933
1993
  }
1934
- if method and self.respond_to?(method)
1994
+
1995
+ if method and target.respond_to?(method)
1935
1996
  subargs[:callback] = method
1936
1997
  end
1937
1998
  Puppet::Event::Subscription.new(subargs)
@@ -2039,8 +2100,8 @@ class Type < Puppet::Element
2039
2100
 
2040
2101
  newmetaparam(:schedule) do
2041
2102
  desc "On what schedule the object should be managed. You must create a
2042
- schedule_ object, and then reference the name of that object to use
2043
- that for your schedule::
2103
+ schedule object, and then reference the name of that object to use
2104
+ that for your schedule:
2044
2105
 
2045
2106
  schedule { daily:
2046
2107
  period => daily,
@@ -2094,7 +2155,13 @@ class Type < Puppet::Element
2094
2155
  end
2095
2156
  next if @parent.statedefined?(state)
2096
2157
 
2097
- next unless @parent.class.validstate?(state).checkable?
2158
+ stateklass = @parent.class.validstate?(state)
2159
+
2160
+ unless stateklass
2161
+ raise Puppet::Error, "%s is not a valid attribute for %s" %
2162
+ [state, self.class.name]
2163
+ end
2164
+ next unless stateklass.checkable?
2098
2165
 
2099
2166
  @parent.newstate(state)
2100
2167
  }
@@ -2105,7 +2172,7 @@ class Type < Puppet::Element
2105
2172
  newmetaparam(:require) do
2106
2173
  desc "One or more objects that this object depends on.
2107
2174
  This is used purely for guaranteeing that changes to required objects
2108
- happen before the dependent object. For instance::
2175
+ happen before the dependent object. For instance:
2109
2176
 
2110
2177
  # Create the destination directory before you copy things down
2111
2178
  file { \"/usr/local/scripts\":
@@ -2128,7 +2195,7 @@ class Type < Puppet::Element
2128
2195
  automatically realize that the parent directory should be created
2129
2196
  before the script is pulled down.
2130
2197
 
2131
- Currently, exec_ elements will autorequire their CWD (if it is
2198
+ Currently, exec elements will autorequire their CWD (if it is
2132
2199
  specified) plus any fully qualified paths that appear in the
2133
2200
  command. For instance, if you had an ``exec`` command that ran
2134
2201
  the ``myscript`` mentioned above, the above code that pulls the
@@ -2151,8 +2218,6 @@ class Type < Puppet::Element
2151
2218
  requires = values + requires
2152
2219
  end
2153
2220
  requires
2154
- #p @parent[:require]
2155
- #@parent.handledepends(requires, :NONE, nil)
2156
2221
  end
2157
2222
  end
2158
2223
 
@@ -2161,17 +2226,16 @@ class Type < Puppet::Element
2161
2226
  newmetaparam(:subscribe) do
2162
2227
  desc "One or more objects that this object depends on. Changes in the
2163
2228
  subscribed to objects result in the dependent objects being
2164
- refreshed (e.g., a service will get restarted). For instance::
2229
+ refreshed (e.g., a service will get restarted). For instance:
2165
2230
 
2166
2231
  class nagios {
2167
2232
  file { \"/etc/nagios/nagios.conf\":
2168
2233
  source => \"puppet://server/module/nagios.conf\",
2169
2234
  alias => nagconf # just to make things easier for me
2170
2235
  }
2171
-
2172
2236
  service { nagios:
2173
2237
  running => true,
2174
- require => file[nagconf]
2238
+ subscribe => file[nagconf]
2175
2239
  }
2176
2240
  }
2177
2241
  "
@@ -2186,11 +2250,9 @@ class Type < Puppet::Element
2186
2250
  end
2187
2251
 
2188
2252
  newmetaparam(:loglevel) do
2189
- desc "Sets the level that information will be logged:
2190
- ``debug``, ``info``, ``verbose``, ``notice``, ``warning``,
2191
- ``err``, ``alert``, ``emerg`` or ``crit``. The log levels have
2192
- the biggest impact when logs are sent to syslog (which is
2193
- currently the default)."
2253
+ desc "Sets the level that information will be logged.
2254
+ The log levels have the biggest impact when logs are sent to
2255
+ syslog (which is currently the default)."
2194
2256
  defaultto :notice
2195
2257
 
2196
2258
  newvalues(*Puppet::Log.levels)
@@ -2207,7 +2269,7 @@ class Type < Puppet::Element
2207
2269
 
2208
2270
  newmetaparam(:alias) do
2209
2271
  desc "Creates an alias for the object. Puppet uses this internally when you
2210
- provide a symbolic name::
2272
+ provide a symbolic name:
2211
2273
 
2212
2274
  file { sshdconfig:
2213
2275
  path => $operatingsystem ? {
@@ -2225,7 +2287,7 @@ class Type < Puppet::Element
2225
2287
  and the library sets that as an alias for the file so the dependency
2226
2288
  lookup for ``sshd`` works. You can use this parameter yourself,
2227
2289
  but note that only the library can use these aliases; for instance,
2228
- the following code will not work::
2290
+ the following code will not work:
2229
2291
 
2230
2292
  file { \"/etc/ssh/sshd_config\":
2231
2293
  owner => root,
@@ -2240,7 +2302,9 @@ class Type < Puppet::Element
2240
2302
  There's no way here for the Puppet parser to know that these two stanzas
2241
2303
  should be affecting the same file.
2242
2304
 
2243
- See the `language tutorial <http://reductivelabs.com/projects/puppet/documentation/languagetutorial>`__ for more information.
2305
+ See the [language tutorial][] for more information.
2306
+
2307
+ [language tutorial]: languagetutorial.html
2244
2308
 
2245
2309
  "
2246
2310
 
@@ -2273,7 +2337,7 @@ class Type < Puppet::Element
2273
2337
  Tags are currently useful for things like applying a subset of a
2274
2338
  host's configuration:
2275
2339
 
2276
- puppetd -v --tag mytag --onetime
2340
+ puppetd --test --tag mytag
2277
2341
 
2278
2342
  This way, when you're testing a configuration you can run just the
2279
2343
  portion you're testing."
@@ -2286,6 +2350,75 @@ class Type < Puppet::Element
2286
2350
  end
2287
2351
  end
2288
2352
  end
2353
+
2354
+ newmetaparam(:notify) do
2355
+ desc %{This parameter is the opposite of **subscribe** -- it sends events
2356
+ to the specified object:
2357
+
2358
+ file { "/etc/sshd_config":
2359
+ source => "....",
2360
+ notify => service[sshd]
2361
+ }
2362
+
2363
+ service { sshd:
2364
+ ensure => running
2365
+ }
2366
+
2367
+ This will restart the sshd service if the sshd config file changes.}
2368
+
2369
+
2370
+ # Take whatever dependencies currently exist and add these.
2371
+ munge do |notifies|
2372
+ # We need to be two arrays deep...
2373
+ unless notifies.is_a?(Array)
2374
+ notifies = [notifies]
2375
+ end
2376
+ unless notifies[0].is_a?(Array)
2377
+ notifies = [notifies]
2378
+ end
2379
+ if values = @parent[:notify]
2380
+ notifies = values + notifies
2381
+ end
2382
+ notifies
2383
+ end
2384
+
2385
+ end
2386
+
2387
+ newmetaparam(:before) do
2388
+ desc %{This parameter is the opposite of **require** -- it guarantees
2389
+ that the specified object is applied later than the specifying
2390
+ object:
2391
+
2392
+ file { "/var/nagios/configuration":
2393
+ source => "...",
2394
+ recurse => true,
2395
+ before => exec["nagios-rebuid"]
2396
+ }
2397
+
2398
+ exec { "nagios-rebuild":
2399
+ command => "/usr/bin/make",
2400
+ cwd => "/var/nagios/configuration"
2401
+ }
2402
+
2403
+ This will make sure all of the files are up to date before the
2404
+ make command is run.}
2405
+
2406
+ # Take whatever dependencies currently exist and add these.
2407
+ munge do |notifies|
2408
+ # We need to be two arrays deep...
2409
+ unless notifies.is_a?(Array)
2410
+ notifies = [notifies]
2411
+ end
2412
+ unless notifies[0].is_a?(Array)
2413
+ notifies = [notifies]
2414
+ end
2415
+ if values = @parent[:notify]
2416
+ notifies = values + notifies
2417
+ end
2418
+ notifies
2419
+ end
2420
+
2421
+ end
2289
2422
  end # Puppet::Type
2290
2423
  end
2291
2424
 
@@ -2304,4 +2437,4 @@ require 'puppet/type/user'
2304
2437
  require 'puppet/type/tidy'
2305
2438
  require 'puppet/type/parsedtype'
2306
2439
 
2307
- # $Id: type.rb 1129 2006-04-21 19:14:59Z luke $
2440
+ # $Id: type.rb 1373 2006-07-06 04:39:59Z luke $