puppet 0.9.2 → 0.13.0

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

Potentially problematic release.


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

Files changed (213) hide show
  1. data/CHANGELOG +58 -0
  2. data/README +21 -18
  3. data/Rakefile +176 -36
  4. data/bin/puppet +34 -48
  5. data/bin/puppetca +41 -28
  6. data/bin/puppetd +87 -65
  7. data/bin/puppetdoc +99 -23
  8. data/bin/puppetmasterd +72 -91
  9. data/conf/redhat/client.init +80 -0
  10. data/conf/redhat/client.sysconfig +11 -0
  11. data/conf/redhat/fileserver.conf +12 -0
  12. data/conf/redhat/puppet.spec +130 -0
  13. data/conf/redhat/server.init +89 -0
  14. data/conf/redhat/server.sysconfig +9 -0
  15. data/examples/code/allatonce +2 -2
  16. data/examples/code/assignments +1 -1
  17. data/examples/code/classing +2 -2
  18. data/examples/code/components +2 -2
  19. data/examples/code/file.bl +5 -5
  20. data/examples/code/filedefaults +2 -2
  21. data/examples/code/fileparsing +1 -1
  22. data/examples/code/filerecursion +1 -1
  23. data/examples/code/functions +1 -1
  24. data/examples/code/groups +1 -1
  25. data/examples/code/importing +1 -1
  26. data/examples/code/nodes +1 -1
  27. data/examples/code/one +1 -1
  28. data/examples/code/relationships +2 -2
  29. data/examples/code/simpletests +5 -5
  30. data/examples/code/snippets/argumentdefaults +2 -2
  31. data/examples/code/snippets/casestatement +16 -8
  32. data/examples/code/snippets/classheirarchy.pp +4 -4
  33. data/examples/code/snippets/classincludes.pp +4 -4
  34. data/examples/code/snippets/classpathtest +2 -2
  35. data/examples/code/snippets/componentmetaparams.pp +11 -0
  36. data/examples/code/snippets/dirchmod +5 -5
  37. data/examples/code/snippets/emptyclass.pp +9 -0
  38. data/examples/code/snippets/failmissingexecpath.pp +1 -1
  39. data/examples/code/snippets/falsevalues.pp +1 -1
  40. data/examples/code/snippets/filecreate +5 -5
  41. data/examples/code/snippets/implicititeration +5 -5
  42. data/examples/code/snippets/multipleinstances +4 -4
  43. data/examples/code/snippets/namevartest +3 -3
  44. data/examples/code/snippets/scopetest +1 -1
  45. data/examples/code/snippets/selectorvalues.pp +3 -3
  46. data/examples/code/snippets/simpledefaults +2 -2
  47. data/examples/code/snippets/simpleselector +5 -5
  48. data/examples/code/snippets/singleary.pp +19 -0
  49. data/examples/root/etc/init.d/sleeper +3 -2
  50. data/ext/emacs/puppet-mode-init.el +6 -0
  51. data/ext/emacs/puppet-mode.el +189 -0
  52. data/ext/ldap/puppet.schema +17 -0
  53. data/ext/{module:puppet → module_puppet} +30 -31
  54. data/ext/vim/filetype.vim +9 -0
  55. data/ext/vim/puppet.vim +87 -0
  56. data/install.rb +63 -30
  57. data/lib/puppet.rb +216 -122
  58. data/lib/puppet/client.rb +51 -416
  59. data/lib/puppet/client/ca.rb +17 -0
  60. data/lib/puppet/client/dipper.rb +78 -0
  61. data/lib/puppet/client/file.rb +20 -0
  62. data/lib/puppet/client/log.rb +17 -0
  63. data/lib/puppet/client/master.rb +246 -0
  64. data/lib/puppet/client/proxy.rb +27 -0
  65. data/lib/puppet/client/status.rb +7 -0
  66. data/lib/puppet/config.rb +563 -13
  67. data/lib/puppet/daemon.rb +50 -22
  68. data/lib/puppet/element.rb +4 -4
  69. data/lib/puppet/event-loop.rb +1 -0
  70. data/lib/puppet/event-loop/better-definers.rb +367 -0
  71. data/lib/puppet/event-loop/event-loop.rb +355 -0
  72. data/lib/puppet/event-loop/signal-system.rb +220 -0
  73. data/lib/puppet/event.rb +9 -11
  74. data/lib/puppet/filetype.rb +195 -0
  75. data/lib/puppet/log.rb +35 -12
  76. data/lib/puppet/metric.rb +2 -2
  77. data/lib/puppet/networkclient.rb +145 -0
  78. data/lib/puppet/parameter.rb +335 -0
  79. data/lib/puppet/parser/ast.rb +42 -1453
  80. data/lib/puppet/parser/ast/astarray.rb +88 -0
  81. data/lib/puppet/parser/ast/branch.rb +47 -0
  82. data/lib/puppet/parser/ast/caseopt.rb +66 -0
  83. data/lib/puppet/parser/ast/casestatement.rb +78 -0
  84. data/lib/puppet/parser/ast/classdef.rb +78 -0
  85. data/lib/puppet/parser/ast/compdef.rb +111 -0
  86. data/lib/puppet/parser/ast/component.rb +105 -0
  87. data/lib/puppet/parser/ast/hostclass.rb +82 -0
  88. data/lib/puppet/parser/ast/leaf.rb +86 -0
  89. data/lib/puppet/parser/ast/node.rb +103 -0
  90. data/lib/puppet/parser/ast/nodedef.rb +68 -0
  91. data/lib/puppet/parser/ast/objectdef.rb +336 -0
  92. data/lib/puppet/parser/ast/objectparam.rb +30 -0
  93. data/lib/puppet/parser/ast/objectref.rb +76 -0
  94. data/lib/puppet/parser/ast/selector.rb +60 -0
  95. data/lib/puppet/parser/ast/typedefaults.rb +45 -0
  96. data/lib/puppet/parser/ast/vardef.rb +44 -0
  97. data/lib/puppet/parser/interpreter.rb +31 -14
  98. data/lib/puppet/parser/lexer.rb +2 -4
  99. data/lib/puppet/parser/parser.rb +332 -242
  100. data/lib/puppet/parser/scope.rb +55 -38
  101. data/lib/puppet/server.rb +43 -44
  102. data/lib/puppet/server/authstore.rb +3 -6
  103. data/lib/puppet/server/ca.rb +5 -2
  104. data/lib/puppet/server/filebucket.rb +2 -4
  105. data/lib/puppet/server/fileserver.rb +28 -12
  106. data/lib/puppet/server/logger.rb +15 -4
  107. data/lib/puppet/server/master.rb +62 -7
  108. data/lib/puppet/sslcertificates.rb +41 -607
  109. data/lib/puppet/sslcertificates/ca.rb +291 -0
  110. data/lib/puppet/sslcertificates/certificate.rb +283 -0
  111. data/lib/puppet/statechange.rb +6 -1
  112. data/lib/puppet/storage.rb +67 -56
  113. data/lib/puppet/transaction.rb +25 -9
  114. data/lib/puppet/transportable.rb +102 -22
  115. data/lib/puppet/type.rb +1096 -315
  116. data/lib/puppet/type/component.rb +30 -21
  117. data/lib/puppet/type/cron.rb +409 -448
  118. data/lib/puppet/type/exec.rb +234 -174
  119. data/lib/puppet/type/group.rb +65 -82
  120. data/lib/puppet/type/nameservice.rb +247 -3
  121. data/lib/puppet/type/nameservice/netinfo.rb +29 -40
  122. data/lib/puppet/type/nameservice/objectadd.rb +52 -66
  123. data/lib/puppet/type/nameservice/posix.rb +6 -194
  124. data/lib/puppet/type/package.rb +447 -295
  125. data/lib/puppet/type/package/apt.rb +51 -50
  126. data/lib/puppet/type/package/bsd.rb +82 -0
  127. data/lib/puppet/type/package/dpkg.rb +85 -88
  128. data/lib/puppet/type/package/rpm.rb +67 -63
  129. data/lib/puppet/type/package/sun.rb +119 -98
  130. data/lib/puppet/type/package/yum.rb +41 -37
  131. data/lib/puppet/type/parsedtype.rb +295 -0
  132. data/lib/puppet/type/parsedtype/host.rb +143 -0
  133. data/lib/puppet/type/parsedtype/port.rb +232 -0
  134. data/lib/puppet/type/parsedtype/sshkey.rb +129 -0
  135. data/lib/puppet/type/pfile.rb +484 -460
  136. data/lib/puppet/type/pfile/checksum.rb +237 -181
  137. data/lib/puppet/type/pfile/content.rb +67 -0
  138. data/lib/puppet/type/pfile/ensure.rb +212 -0
  139. data/lib/puppet/type/pfile/group.rb +106 -105
  140. data/lib/puppet/type/pfile/mode.rb +98 -101
  141. data/lib/puppet/type/pfile/source.rb +228 -209
  142. data/lib/puppet/type/pfile/type.rb +18 -21
  143. data/lib/puppet/type/pfile/uid.rb +127 -130
  144. data/lib/puppet/type/pfilebucket.rb +68 -63
  145. data/lib/puppet/type/schedule.rb +341 -0
  146. data/lib/puppet/type/service.rb +351 -255
  147. data/lib/puppet/type/service/base.rb +9 -14
  148. data/lib/puppet/type/service/debian.rb +32 -38
  149. data/lib/puppet/type/service/init.rb +130 -130
  150. data/lib/puppet/type/service/smf.rb +48 -20
  151. data/lib/puppet/type/state.rb +229 -16
  152. data/lib/puppet/type/symlink.rb +51 -63
  153. data/lib/puppet/type/tidy.rb +105 -102
  154. data/lib/puppet/type/user.rb +118 -180
  155. data/lib/puppet/util.rb +100 -6
  156. data/test/certmgr/certmgr.rb +0 -1
  157. data/test/client/client.rb +4 -4
  158. data/test/executables/puppetbin.rb +7 -14
  159. data/test/executables/puppetca.rb +18 -24
  160. data/test/executables/puppetd.rb +7 -16
  161. data/test/executables/puppetmasterd.rb +7 -9
  162. data/test/executables/puppetmodule.rb +11 -16
  163. data/test/language/ast.rb +11 -7
  164. data/test/language/interpreter.rb +1 -1
  165. data/test/language/scope.rb +2 -0
  166. data/test/language/snippets.rb +30 -5
  167. data/test/language/transportable.rb +77 -0
  168. data/test/other/config.rb +316 -0
  169. data/test/other/events.rb +22 -21
  170. data/test/other/log.rb +14 -14
  171. data/test/other/metrics.rb +4 -8
  172. data/test/other/overrides.rb +5 -5
  173. data/test/other/relationships.rb +4 -2
  174. data/test/other/storage.rb +64 -3
  175. data/test/other/transactions.rb +20 -20
  176. data/test/parser/parser.rb +7 -4
  177. data/test/puppet/conffiles.rb +12 -12
  178. data/test/puppet/defaults.rb +13 -11
  179. data/test/puppet/utiltest.rb +14 -11
  180. data/test/puppettest.rb +156 -48
  181. data/test/server/bucket.rb +2 -2
  182. data/test/server/fileserver.rb +6 -6
  183. data/test/server/logger.rb +19 -11
  184. data/test/server/master.rb +33 -4
  185. data/test/server/server.rb +2 -7
  186. data/test/types/basic.rb +5 -7
  187. data/test/types/component.rb +22 -18
  188. data/test/types/cron.rb +111 -44
  189. data/test/types/exec.rb +116 -59
  190. data/test/types/file.rb +262 -137
  191. data/test/types/filebucket.rb +13 -15
  192. data/test/types/fileignoresource.rb +12 -16
  193. data/test/types/filesources.rb +73 -48
  194. data/test/types/filetype.rb +13 -15
  195. data/test/types/group.rb +15 -13
  196. data/test/types/host.rb +146 -0
  197. data/test/types/package.rb +74 -63
  198. data/test/types/port.rb +139 -0
  199. data/test/types/query.rb +8 -8
  200. data/test/types/schedule.rb +335 -0
  201. data/test/types/service.rb +137 -21
  202. data/test/types/sshkey.rb +140 -0
  203. data/test/types/symlink.rb +3 -5
  204. data/test/types/tidy.rb +5 -14
  205. data/test/types/type.rb +67 -11
  206. data/test/types/user.rb +25 -23
  207. metadata +186 -122
  208. data/lib/puppet/type/pfile/create.rb +0 -108
  209. data/lib/puppet/type/pprocess.rb +0 -97
  210. data/lib/puppet/type/typegen.rb +0 -149
  211. data/lib/puppet/type/typegen/filerecord.rb +0 -243
  212. data/lib/puppet/type/typegen/filetype.rb +0 -316
  213. data/test/other/state.rb +0 -106
@@ -4,15 +4,21 @@ require 'puppet/element'
4
4
  require 'puppet/event'
5
5
  require 'puppet/metric'
6
6
  require 'puppet/type/state'
7
+ require 'puppet/parameter'
8
+ require 'puppet/util'
7
9
  # see the bottom of the file for the rest of the inclusions
8
10
 
9
- module Puppet # :nodoc:
10
- # This class is the abstract base class for the mechanism for organizing
11
- # work. No work is actually done by this class or its subclasses; rather,
12
- # the subclasses include states which do the actual work.
13
- # See state.rb for how work is actually done.
11
+ module Puppet
14
12
  class Type < Puppet::Element
15
- attr_accessor :children, :parameters, :parent
13
+ # Types (which map to elements in the languages) are entirely composed of
14
+ # attribute value pairs. Generally, Puppet calls any of these things an
15
+ # 'attribute', but these attributes always take one of three specific
16
+ # forms: parameters, metaparams, or states.
17
+
18
+ # In naming methods, I have tried to consistently name the method so
19
+ # that it is clear whether it operates on all attributes (thus has 'attr' in
20
+ # the method name, or whether it operates on a specific type of attributes.
21
+ attr_accessor :children, :parent
16
22
  attr_accessor :file, :line, :tags
17
23
 
18
24
  attr_writer :implicit
@@ -36,123 +42,105 @@ class Type < Puppet::Element
36
42
  # a little fakery, since Puppet itself isn't a type
37
43
  # I don't think this is used any more, now that the language can't
38
44
  # call methods
39
- @name = :puppet
45
+ #@name = :puppet
40
46
 
41
47
  # set it to something to silence the tests, but otherwise not used
42
- @namevar = :notused
48
+ #@namevar = :notused
43
49
 
44
50
  # again, silence the tests; the :notused has to be there because it's
45
51
  # the namevar
46
- @states = []
47
- @parameters = [:notused]
48
52
 
49
- # @paramdoc = Hash.new
50
-
51
- # the parameters that all instances will accept
52
- @@metaparams = [
53
- :onerror,
54
- :noop,
55
- :schedule,
56
- :check,
57
- :subscribe,
58
- :require,
59
- :loglevel
60
- ]
61
-
62
- @@metaparamdoc = Hash.new { |hash,key|
63
- if key.is_a?(String)
64
- key = key.intern
65
- end
66
- if hash.include?(key)
67
- hash[key]
68
- else
69
- "Metaparam Documentation for %s not found" % key
70
- end
71
- }
72
-
73
- @@metaparamdoc[:onerror] = "How to handle errors -- roll back innermost
74
- transaction, roll back entire transaction, ignore, etc. Currently
75
- non-functional."
76
- @@metaparamdoc[:noop] = "Boolean flag indicating whether work should actually
77
- be done."
78
- @@metaparamdoc[:schedule] = "On what schedule the object should be managed.
79
- Currently non-functional."
80
- @@metaparamdoc[:check] = "States which should have their values retrieved
81
- but which should not actually be modified. This is currently used
82
- internally, but will eventually be used for querying."
83
- @@metaparamdoc[:require] = "One or more objects that this object depends on.
84
- This is used purely for guaranteeing that changes to required objects
85
- happen before the dependent object."
86
- @@metaparamdoc[:subscribe] = "One or more objects that this object depends on.
87
- Changes in the subscribed to objects result in the dependent objects being
88
- refreshed (e.g., a service will get restarted)."
89
- @@metaparamdoc[:loglevel] = "Sets the level that information will be logged:
90
- debug, info, verbose, notice, warning, err, alert, emerg or crit"
91
-
92
53
  # class methods dealing with Type management
93
54
 
94
55
  public
95
56
 
96
- # these objects are used for mapping type names (e.g., 'file')
97
- # to actual object classes; because Type.inherited is
98
- # called before the <subclass>.name method is defined, we need
99
- # to store each class in an array, and then later actually iterate
100
- # across that array and make a map
101
- @@typeary = [self] # so that the allowedmethods stuff works
102
- @@typehash = Hash.new { |hash,key|
103
- if key.is_a?(String)
104
- key = key.intern
57
+ # the Type class attribute accessors
58
+ class << self
59
+ attr_reader :name, :states
60
+
61
+ include Enumerable
62
+
63
+ def inspect
64
+ Puppet.info "inspecting class with name %s" % self.name
65
+ "Type(%s)" % self.name
105
66
  end
106
- if hash.include?(key)
107
- hash[key]
108
- else
109
- raise TypeError.new("Object type %s not found" % key)
67
+
68
+ # This class is aggregatable, meaning that instances are defined on
69
+ # one system but instantiated on another
70
+ def isaggregatable
71
+ @aggregatable = true
110
72
  end
111
- }
112
73
 
113
- # the Type class attribute accessors
114
- class << self
115
- attr_reader :name, :namevar, :states, :parameters
116
- end
117
-
118
- # Create @@typehash from @@typeary. This is meant to be run
119
- # multiple times -- whenever it is discovered that the two
120
- # objects have differents lengths.
121
- def self.buildtypehash
122
- @@typeary.each { |otype|
123
- if @@typehash.include?(otype.name)
124
- if @@typehash[otype.name] != otype
125
- Puppet.warning("Object type %s is already defined (%s vs %s)" %
126
- [otype.name,@@typehash[otype.name],otype])
127
- end
74
+ # Is this one aggregatable?
75
+ def aggregatable?
76
+ if defined? @aggregatable
77
+ return @aggregatable
128
78
  else
129
- @@typehash[otype.name] = otype
79
+ return false
130
80
  end
131
- }
81
+ end
82
+ end
83
+
84
+ def inspect
85
+ str = "Type(%s)" % self.name
86
+ if defined? @states
87
+ str += " States(" + @states.inspect + ")"
88
+ end
89
+ if defined? @parameters
90
+ str += " Parameters(" + @parameters.inspect + ")"
91
+ end
92
+ if defined? @metaparams
93
+ str += " Metaparams(" + @metaparams.inspect + ")"
94
+ end
95
+ str
132
96
  end
133
97
 
134
98
  # iterate across all of the subclasses of Type
135
99
  def self.eachtype
136
- @@typeary.each { |type| yield type }
100
+ @types.each do |name, type|
101
+ # Only consider types that have names
102
+ #if ! type.parameters.empty? or ! type.validstates.empty?
103
+ yield type
104
+ #end
105
+ end
106
+ end
107
+
108
+ # Should we add the 'ensure' state to this class?
109
+ def self.ensurable?
110
+ # If the class has all three of these methods defined, then it's
111
+ # ensurable.
112
+ #ens = [:create, :destroy].inject { |set, method|
113
+ ens = [:exists?, :create, :destroy].inject { |set, method|
114
+ set &&= self.public_method_defined?(method)
115
+ }
116
+
117
+ #puts "%s ensurability: %s" % [self.name, ens]
118
+
119
+ return ens
137
120
  end
138
121
 
139
122
  # The work that gets done for every subclass of Type
140
123
  # this is an implicit method called by Ruby for us
141
- def self.inherited(sub)
142
- sub.initvars
124
+ #def self.inherited(sub)
125
+ # sub.initvars
143
126
 
144
127
  #debug("subtype %s(%s) just created" % [sub,sub.superclass])
145
128
  # add it to the master list
146
129
  # unfortunately we can't yet call sub.name, because the #inherited
147
130
  # method gets called before any commands in the class definition
148
131
  # get executed, which, um, sucks
149
- @@typeary.push(sub)
150
- end
132
+ #@@typeary.push(sub)
133
+ #end
151
134
 
152
135
  # all of the variables that must be initialized for each subclass
153
136
  def self.initvars
154
137
  # all of the instances of this class
155
138
  @objects = Hash.new
139
+ @aliases = Hash.new
140
+
141
+ unless defined? @parameters
142
+ @parameters = []
143
+ end
156
144
 
157
145
  @validstates = {}
158
146
 
@@ -177,24 +165,93 @@ class Type < Puppet::Element
177
165
 
178
166
  end
179
167
 
180
- # return a Type instance by name
181
- def self.type(type)
182
- unless @@typeary.length == @@typehash.length
183
- # call bulidtypehash if types have been added since it
184
- # was last called
185
- Type.buildtypehash
168
+ # Define a new type.
169
+ def self.newtype(name, parent = nil, &block)
170
+ parent ||= Puppet::Type
171
+ Puppet::Util.symbolize(name)
172
+
173
+
174
+ # Create the class, with the correct name.
175
+ t = Class.new(parent) do
176
+ @name = name
177
+ end
178
+ const_set(name.to_s.capitalize,t)
179
+
180
+ # Initialize any necessary variables.
181
+ t.initvars
182
+
183
+ # Evaluate the passed block. This should usually define all of the work.
184
+ t.class_eval(&block)
185
+
186
+ # If they've got all the necessary methods defined and they haven't
187
+ # already added the state, then do so now.
188
+ if t.ensurable? and ! t.validstate?(:ensure)
189
+ t.ensurable
190
+ end
191
+
192
+ @types ||= {}
193
+
194
+ # And add it to our bucket.
195
+ @types[name] = t
196
+ end
197
+
198
+ # Create the 'ensure' class. This is a separate method so other types
199
+ # can easily call it and create their own 'ensure' values.
200
+ def self.ensurable(&block)
201
+ if block_given?
202
+ self.newstate(:ensure, Puppet::State::Ensure, &block)
203
+ else
204
+ self.newstate(:ensure, Puppet::State::Ensure) do
205
+ self.defaultvalues
206
+ end
207
+ end
208
+ end
209
+
210
+ # Return a Type instance by name.
211
+ def self.type(name)
212
+ @types ||= {}
213
+
214
+ if name.is_a?(String)
215
+ name = name.intern
186
216
  end
187
- @@typehash[type]
217
+
218
+ @types[name]
188
219
  end
189
220
 
190
221
  # class methods dealing with type instance management
191
222
 
192
223
  public
193
224
 
225
+ # Create an alias. We keep these in a separate hash so that we don't encounter
226
+ # the objects multiple times when iterating over them.
227
+ def self.alias(name, obj)
228
+ if @objects.include?(name)
229
+ unless @objects[name] == obj
230
+ raise Puppet::Error.new(
231
+ "Cannot create alias %s: object already exists" %
232
+ [name]
233
+ )
234
+ end
235
+ end
236
+
237
+ if @aliases.include?(name)
238
+ unless @aliases[name] == obj
239
+ raise Puppet::Error.new(
240
+ "Object %s already has alias %s" %
241
+ [@aliases[name].name, name]
242
+ )
243
+ end
244
+ end
245
+
246
+ @aliases[name] = obj
247
+ end
248
+
194
249
  # retrieve a named instance of the current type
195
250
  def self.[](name)
196
251
  if @objects.has_key?(name)
197
252
  return @objects[name]
253
+ elsif @aliases.has_key?(name)
254
+ return @aliases[name]
198
255
  else
199
256
  return nil
200
257
  end
@@ -209,16 +266,16 @@ class Type < Puppet::Element
209
266
  raise Puppet::DevError, "must pass a Puppet::Type object"
210
267
  end
211
268
 
212
- if @objects.has_key?(newobj.name) and self.isomorphic?
269
+ if @objects.has_key?(name) and self.isomorphic?
213
270
  raise Puppet::Error.new(
214
271
  "Object '%s' of type '%s' already exists with id '%s' vs. '%s'" %
215
- [newobj.name,newobj.class.name,
216
- @objects[newobj.name].object_id,newobj.object_id]
272
+ [name, newobj.class.name,
273
+ @objects[name].object_id,newobj.object_id]
217
274
  )
218
275
  else
219
- #debug("adding %s of type %s to class list" %
220
- # [object.name,object.class])
221
- @objects[newobj.name] = newobj
276
+ #Puppet.info("adding %s of type %s to class list" %
277
+ # [name,object.class])
278
+ @objects[name] = newobj
222
279
  end
223
280
 
224
281
  # and then add it to the master list
@@ -229,9 +286,10 @@ class Type < Puppet::Element
229
286
  def self.allclear
230
287
  @@allobjects.clear
231
288
  Puppet::Event::Subscription.clear
232
- @@typeary.each { |subtype|
233
- subtype.clear
289
+ @types.each { |name, type|
290
+ type.clear
234
291
  }
292
+ @finalized = false
235
293
  end
236
294
 
237
295
  # remove all of the instances of a single type
@@ -239,6 +297,9 @@ class Type < Puppet::Element
239
297
  if defined? @objects
240
298
  @objects.clear
241
299
  end
300
+ if defined? @aliases
301
+ @aliases.clear
302
+ end
242
303
  end
243
304
 
244
305
  # remove a specified object
@@ -260,6 +321,32 @@ class Type < Puppet::Element
260
321
  }
261
322
  end
262
323
 
324
+ # Perform any operations that need to be done between instance creation
325
+ # and instance evaluation.
326
+ def self.finalize
327
+ finished = {}
328
+ self.eachtype do |type|
329
+ type.each do |object|
330
+ unless finished.has_key?(object)
331
+ object.finish
332
+ finished[object] = true
333
+ end
334
+ end
335
+ end
336
+ self.mkdepends
337
+
338
+ @finalized = true
339
+ end
340
+
341
+ # Has the finalize method been called yet?
342
+ def self.finalized?
343
+ if defined? @finalized
344
+ return @finalized
345
+ else
346
+ return false
347
+ end
348
+ end
349
+
263
350
  # does the type have an object with the given name?
264
351
  def self.has_key?(name)
265
352
  return @objects.has_key?(name)
@@ -300,6 +387,7 @@ class Type < Puppet::Element
300
387
  unless defined? @validstates
301
388
  @validstates = Hash.new(false)
302
389
  end
390
+ return unless defined? @states
303
391
  @states.each { |stateklass|
304
392
  name = stateklass.name
305
393
  if @validstates.include?(name)
@@ -315,19 +403,187 @@ class Type < Puppet::Element
315
403
  }
316
404
  end
317
405
 
318
- # set the parameters for a type; probably only used by FileRecord
319
- # objects
320
- def self.parameters=(params)
321
- Puppet.debug "setting parameters to [%s]" % params.join(" ")
322
- @parameters = params.collect { |param|
323
- if param.class == Symbol
324
- param
325
- else
326
- param.intern
327
- end
406
+ # Find the namevar
407
+ def self.namevar
408
+ unless defined? @namevar
409
+ return nil unless defined? @parameters and ! @parameters.empty?
410
+ @namevar = @parameters.find { |name, param|
411
+ param.isnamevar?
412
+ unless param
413
+ raise Puppet::DevError, "huh? %s" % name
414
+ end
415
+ }[0].value
416
+ end
417
+ @namevar
418
+ end
419
+
420
+ # Copy an existing class parameter. This allows other types to avoid
421
+ # duplicating a parameter definition, and is mostly used by subclasses
422
+ # of the File class.
423
+ def self.copyparam(klass, name)
424
+ param = klass.attrclass(name)
425
+
426
+ unless param
427
+ raise Puppet::DevError, "Class %s has no param %s" % [klass, name]
428
+ end
429
+ @parameters ||= []
430
+ @parameters << param
431
+
432
+ @paramhash ||= {}
433
+ @parameters.each { |p| @paramhash[name] = p }
434
+
435
+ if param.isnamevar?
436
+ @namevar = param.name
437
+ end
438
+ end
439
+
440
+ # Create a new metaparam. Requires a block and a name, stores it in the
441
+ # @parameters array, and does some basic checking on it.
442
+ def self.newmetaparam(name, &block)
443
+ Puppet::Util.symbolize(name)
444
+ param = Class.new(Puppet::Parameter) do
445
+ @name = name
446
+ end
447
+ param.ismetaparameter
448
+ param.class_eval(&block)
449
+ const_set("MetaParam" + name.to_s.capitalize,param)
450
+ @@metaparams ||= []
451
+ @@metaparams << param
452
+
453
+ @@metaparamhash ||= {}
454
+ @@metaparams.each { |p| @@metaparamhash[name] = p }
455
+ end
456
+
457
+ def self.eachmetaparam
458
+ @@metaparams.each { |p| yield p.name }
459
+ end
460
+
461
+ # Create a new parameter. Requires a block and a name, stores it in the
462
+ # @parameters array, and does some basic checking on it.
463
+ def self.newparam(name, &block)
464
+ Puppet::Util.symbolize(name)
465
+ param = Class.new(Puppet::Parameter) do
466
+ @name = name
467
+ end
468
+ param.element = self
469
+ param.class_eval(&block)
470
+ const_set("Parameter" + name.to_s.capitalize,param)
471
+ @parameters ||= []
472
+ @parameters << param
473
+
474
+ @paramhash ||= {}
475
+ @parameters.each { |p| @paramhash[name] = p }
476
+
477
+ # These might be enabled later.
478
+ # define_method(name) do
479
+ # @parameters[name].value
480
+ # end
481
+ #
482
+ # define_method(name.to_s + "=") do |value|
483
+ # newparam(param, value)
484
+ # end
485
+
486
+ if param.isnamevar?
487
+ @namevar = param.name
488
+ end
489
+ end
490
+
491
+ # Create a new state.
492
+ def self.newstate(name, parent = nil, &block)
493
+ parent ||= Puppet::State
494
+ if @validstates.include?(name)
495
+ raise Puppet::DevError, "Class %s already has a state named %s" %
496
+ [self.name, name]
497
+ end
498
+ s = Class.new(parent) do
499
+ @name = name
500
+ end
501
+ const_set("State" + name.to_s.capitalize,s)
502
+ s.class_eval(&block)
503
+ @states ||= []
504
+
505
+ # If it's the 'ensure' state, always put it first.
506
+ if name == :ensure
507
+ @states.unshift s
508
+ else
509
+ @states << s
510
+ end
511
+ @validstates[name] = s
512
+
513
+ # define_method(name) do
514
+ # @states[name].should
515
+ # end
516
+ #
517
+ # define_method(name.to_s + "=") do |value|
518
+ # newstate(name, :should => value)
519
+ # end
520
+
521
+ return s
522
+ end
523
+
524
+ # Specify a block for generating a list of objects to autorequire. This
525
+ # makes it so that you don't have to manually specify things that you clearly
526
+ # require.
527
+ def self.autorequire(name, &block)
528
+ @autorequires ||= {}
529
+ @autorequires[name] = block
530
+ end
531
+
532
+ # Yield each of those autorequires in turn, yo.
533
+ def self.eachautorequire
534
+ @autorequires ||= {}
535
+ @autorequires.each { |type, block|
536
+ yield(type, block)
328
537
  }
329
538
  end
330
539
 
540
+ # Return the parameter names
541
+ def self.parameters
542
+ return [] unless defined? @parameters
543
+ @parameters.collect { |klass| klass.name }
544
+ end
545
+
546
+ # Find the metaparameter class associated with a given metaparameter name.
547
+ def self.metaparamclass(name)
548
+ @@metaparamhash[name]
549
+ end
550
+
551
+ # Find the parameter class associated with a given parameter name.
552
+ def self.paramclass(name)
553
+ @paramhash[name]
554
+ end
555
+
556
+ # Find the class associated with any given attribute.
557
+ def self.attrclass(name)
558
+ @attrclasses ||= {}
559
+
560
+ # We cache the value, since this method gets called such a huge number
561
+ # of times (as in, hundreds of thousands in a given run).
562
+ unless @attrclasses.include?(name)
563
+ @attrclasses[name] = case self.attrtype(name)
564
+ when :state: @validstates[name]
565
+ when :meta: @@metaparamhash[name]
566
+ when :param: @paramhash[name]
567
+ end
568
+ end
569
+ @attrclasses[name]
570
+ end
571
+
572
+ def self.to_s
573
+ if defined? @name
574
+ "Puppet::Type::" + @name.to_s.capitalize
575
+ else
576
+ super
577
+ end
578
+ end
579
+
580
+ # Create a block to validate that our object is set up entirely. This will
581
+ # be run before the object is operated on.
582
+ def self.validate(&block)
583
+ define_method(:validate, &block)
584
+ #@validate = block
585
+ end
586
+
331
587
  # does the name reflect a valid state?
332
588
  def self.validstate?(name)
333
589
  unless @validstates.length == @states.length
@@ -342,6 +598,7 @@ class Type < Puppet::Element
342
598
 
343
599
  # Return the list of validstates
344
600
  def self.validstates
601
+ return {} unless defined? @states
345
602
  unless @validstates.length == @states.length
346
603
  self.buildstatehash
347
604
  end
@@ -362,14 +619,75 @@ class Type < Puppet::Element
362
619
  unless defined? @parameters
363
620
  raise Puppet::DevError, "Class %s has not defined parameters" % self
364
621
  end
365
- if @parameters.include?(name) or @@metaparams.include?(name)
622
+ if @paramhash.include?(name) or @@metaparamhash.include?(name)
366
623
  return true
367
624
  else
368
625
  return false
369
626
  end
370
627
  end
371
628
 
372
- def self.validarg?(name)
629
+ # What type of parameter are we dealing with? Cache the results, because
630
+ # this method gets called so many times.
631
+ def self.attrtype(name)
632
+ @attrtypes ||= {}
633
+ unless @attrtypes.include?(name)
634
+ @attrtypes[name] = case
635
+ when @validstates.include?(name): :state
636
+ when @@metaparamhash.include?(name): :meta
637
+ when @paramhash.include?(name): :param
638
+ else
639
+ raise Puppet::DevError, "Invalid attribute '%s' for class '%s'" %
640
+ [name, self.name]
641
+ end
642
+ end
643
+
644
+ @attrtypes[name]
645
+ end
646
+
647
+ # All parameters, in the appropriate order. The namevar comes first,
648
+ # then the states, then the params and metaparams in the order they
649
+ # were specified in the files.
650
+ def self.allattrs
651
+ # now get all of the arguments, in a specific order
652
+ # Cache this, since it gets called so many times
653
+ namevar = self.namevar
654
+
655
+ order = [namevar]
656
+ order << [self.states.collect { |state| state.name },
657
+ self.parameters,
658
+ self.metaparams].flatten.reject { |param|
659
+ # we don't want our namevar in there multiple times
660
+ param == namevar
661
+ }
662
+
663
+ order.flatten!
664
+
665
+ return order
666
+ end
667
+
668
+ # A similar function but one that yields the name, type, and class.
669
+ # This is mainly so that setdefaults doesn't call quite so many functions.
670
+ def self.eachattr(*ary)
671
+ # now get all of the arguments, in a specific order
672
+ # Cache this, since it gets called so many times
673
+
674
+ if ary.empty?
675
+ ary = nil
676
+ end
677
+ self.states.each { |state|
678
+ yield(state, :state) if ary.nil? or ary.include?(state.name)
679
+ }
680
+
681
+ @parameters.each { |param|
682
+ yield(param, :param) if ary.nil? or ary.include?(param.name)
683
+ }
684
+
685
+ @@metaparams.each { |param|
686
+ yield(param, :meta) if ary.nil? or ary.include?(param.name)
687
+ }
688
+ end
689
+
690
+ def self.validattr?(name)
373
691
  if name.is_a?(String)
374
692
  name = name.intern
375
693
  end
@@ -393,26 +711,35 @@ class Type < Puppet::Element
393
711
  if name == :name
394
712
  name = self.class.namevar
395
713
  end
396
- if self.class.validstate?(name)
714
+ case self.class.attrtype(name)
715
+ when :state
397
716
  if @states.include?(name)
398
717
  return @states[name].is
399
718
  else
400
719
  return nil
401
720
  end
402
- elsif Puppet::Type.metaparam?(name)
721
+ when :meta
403
722
  if @metaparams.include?(name)
404
- return @metaparams[name]
723
+ return @metaparams[name].value
405
724
  else
406
- return nil
725
+ if default = self.class.metaparamclass(name).default
726
+ return default
727
+ else
728
+ return nil
729
+ end
407
730
  end
408
- elsif self.class.validparameter?(name)
731
+ when :param
409
732
  if @parameters.include?(name)
410
- return @parameters[name]
733
+ return @parameters[name].value
411
734
  else
412
- return nil
735
+ if default = self.class.paramclass(name).default
736
+ return default
737
+ else
738
+ return nil
739
+ end
413
740
  end
414
741
  else
415
- raise TypeError.new("Invalid parameter %s" % [name])
742
+ raise TypeError.new("Invalid parameter %s(%s)" % [name, name.inspect])
416
743
  end
417
744
  end
418
745
 
@@ -430,11 +757,9 @@ class Type < Puppet::Element
430
757
  if value.nil?
431
758
  raise Puppet::Error.new("Got nil value for %s" % name)
432
759
  end
433
- if Puppet::Type.metaparam?(name)
434
- @parameters[name] = value
435
- # call the metaparam method
436
- self.send(("meta" + name.id2name + "="),value)
437
- elsif stateklass = self.class.validstate?(name)
760
+
761
+ case self.class.attrtype(name)
762
+ when :state
438
763
  if value.is_a?(Puppet::State)
439
764
  self.debug "'%s' got handed a state for '%s'" % [self,name]
440
765
  @states[name] = value
@@ -450,15 +775,11 @@ class Type < Puppet::Element
450
775
  end
451
776
  end
452
777
  end
453
- elsif self.class.validparameter?(name)
778
+ when :meta
779
+ self.newmetaparam(self.class.metaparamclass(name), value)
780
+ when :param
454
781
  # if they've got a method to handle the parameter, then do it that way
455
- method = "param" + name.id2name + "="
456
- if self.respond_to?(method)
457
- self.send(method,value)
458
- else
459
- # else just set it
460
- @parameters[name] = value
461
- end
782
+ self.newparam(self.class.attrclass(name), value)
462
783
  else
463
784
  raise Puppet::Error, "Invalid parameter %s" % [name]
464
785
  end
@@ -475,8 +796,12 @@ class Type < Puppet::Element
475
796
  else
476
797
  if @states.has_key?(attr)
477
798
  @states.delete(attr)
799
+ elsif @parameters.has_key?(attr)
800
+ @parameters.delete(attr)
801
+ elsif @metaparams.has_key?(attr)
802
+ @metaparams.delete(attr)
478
803
  else
479
- raise Puppet::DevError.new("Undefined state '#{attr}' in #{self}")
804
+ raise Puppet::DevError.new("Undefined attribute '#{attr}' in #{self}")
480
805
  end
481
806
  end
482
807
  end
@@ -513,6 +838,32 @@ class Type < Puppet::Element
513
838
  }
514
839
  end
515
840
 
841
+ def devfail(msg)
842
+ self.fail(Puppet::DevError, msg)
843
+ end
844
+
845
+ # Throw an error, defaulting to a Puppet::Error
846
+ def fail(*args)
847
+ type = nil
848
+ if args[0].is_a?(Class)
849
+ type = args.shift
850
+ else
851
+ type = Puppet::Error
852
+ end
853
+
854
+ error = type.new(args.join(" "))
855
+
856
+ if defined? @line and @line
857
+ error.line = @line
858
+ end
859
+
860
+ if defined? @file and @file
861
+ error.file = @file
862
+ end
863
+
864
+ raise error
865
+ end
866
+
516
867
  # retrieve the 'is' value for a specified state
517
868
  def is(state)
518
869
  if @states.include?(state)
@@ -534,7 +885,7 @@ class Type < Puppet::Element
534
885
  # create a log at specified level
535
886
  def log(msg)
536
887
  Puppet::Log.create(
537
- :level => @metaparams[:loglevel],
888
+ :level => @metaparams[:loglevel].value,
538
889
  :message => msg,
539
890
  :source => self
540
891
  )
@@ -558,10 +909,52 @@ class Type < Puppet::Element
558
909
  end
559
910
  end
560
911
 
912
+ # Create a new parameter.
913
+ def newparam(klass, value = nil)
914
+ newattr(:param, klass, value)
915
+ end
916
+
917
+ # Create a new parameter or metaparameter. We'll leave the calling
918
+ # method to store it appropriately.
919
+ def newmetaparam(klass, value = nil)
920
+ newattr(:meta, klass, value)
921
+ end
922
+
923
+ # The base function that the others wrap.
924
+ def newattr(type, klass, value = nil)
925
+ # This should probably be a bit, um, different, but...
926
+ if type == :state
927
+ return newstate(klass)
928
+ end
929
+ param = klass.new
930
+ param.parent = self
931
+ if value
932
+ param.value = value
933
+ end
934
+
935
+ case type
936
+ when :meta
937
+ @metaparams[klass.name] = param
938
+ when :param
939
+ @parameters[klass.name] = param
940
+ else
941
+ self.devfail("Invalid param type %s" % type)
942
+ end
943
+
944
+ return param
945
+ end
946
+
561
947
  # create a new state
562
948
  def newstate(name, hash = {})
563
- unless stateklass = self.class.validstate?(name)
564
- raise Puppet::Error, "Invalid parameter %s" % name
949
+ stateklass = nil
950
+ if name.is_a?(Class)
951
+ stateklass = name
952
+ name = stateklass.name
953
+ else
954
+ stateklass = self.class.validstate?(name)
955
+ unless stateklass
956
+ self.fail("Invalid state %s" % name)
957
+ end
565
958
  end
566
959
  if @states.include?(name)
567
960
  hash.each { |var,value|
@@ -575,7 +968,7 @@ class Type < Puppet::Element
575
968
  # make sure the state doesn't have any errors
576
969
  newstate = stateklass.new(hash)
577
970
  @states[name] = newstate
578
- return true
971
+ return newstate
579
972
  rescue Puppet::Error => detail
580
973
  # the state failed, so just ignore it
581
974
  self.warning "State %s failed: %s" %
@@ -600,7 +993,7 @@ class Type < Puppet::Element
600
993
  unless name.is_a? Symbol
601
994
  name = name.intern
602
995
  end
603
- return @parameters[name]
996
+ return @parameters[name].value
604
997
  end
605
998
 
606
999
  def push(*childs)
@@ -615,23 +1008,35 @@ class Type < Puppet::Element
615
1008
 
616
1009
  # Remove an object. The argument determines whether the object's
617
1010
  # subscriptions get eliminated, too.
618
- def remove(rmdeps)
1011
+ def remove(rmdeps = true)
619
1012
  @children.each { |child|
620
- child.remove
1013
+ child.remove(rmdeps)
621
1014
  }
622
- self.class.delete(self)
623
1015
 
624
1016
  if rmdeps
625
1017
  Puppet::Event::Subscription.dependencies(self).each { |dep|
626
- self.unsubscribe(dep)
1018
+ begin
1019
+ self.unsubscribe(dep)
1020
+ rescue
1021
+ # ignore failed unsubscribes
1022
+ end
627
1023
  }
628
1024
  end
1025
+ self.class.delete(self)
629
1026
 
630
1027
  if defined? @parent and @parent
631
1028
  @parent.delete(self)
632
1029
  end
633
1030
  end
634
1031
 
1032
+ # Is the named state defined?
1033
+ def statedefined?(name)
1034
+ unless name.is_a? Symbol
1035
+ name = name.intern
1036
+ end
1037
+ return @states.include?(name)
1038
+ end
1039
+
635
1040
  # return an actual type by name; to return the value, use 'inst[name]'
636
1041
  # FIXME this method should go away
637
1042
  def state(name)
@@ -652,8 +1057,9 @@ class Type < Puppet::Element
652
1057
  end
653
1058
  }
654
1059
  unless tmpstates.length == @states.length
655
- raise Puppet::DevError,
1060
+ self.devfail(
656
1061
  "Something went very wrong with tmpstates creation"
1062
+ )
657
1063
  end
658
1064
  return tmpstates
659
1065
  end
@@ -697,7 +1103,7 @@ class Type < Puppet::Element
697
1103
  else
698
1104
  # We will probably want to support merging of some kind in
699
1105
  # the future, but for now, just throw an error.
700
- raise Puppet::Error, "%s %s is already being managed" %
1106
+ raise Puppet::Error, "%s '%s' is already being managed" %
701
1107
  [self.name, name]
702
1108
  #retobj.merge(hash)
703
1109
 
@@ -711,9 +1117,7 @@ class Type < Puppet::Element
711
1117
  obj = new(hash)
712
1118
  rescue => detail
713
1119
  if Puppet[:debug]
714
- if detail.respond_to?(:stack)
715
- puts detail.stack
716
- end
1120
+ puts detail.backtrace
717
1121
  end
718
1122
  Puppet.err "Could not create %s: %s" % [name, detail.to_s]
719
1123
  if obj
@@ -757,8 +1161,7 @@ class Type < Puppet::Element
757
1161
  private :new
758
1162
  end
759
1163
 
760
- # initialize the type instance
761
- def initialize(hash)
1164
+ def initvars
762
1165
  @children = []
763
1166
  @evalcount = 0
764
1167
 
@@ -782,72 +1185,245 @@ class Type < Puppet::Element
782
1185
  unless defined? @metaparams
783
1186
  @metaparams = Hash.new(false)
784
1187
  end
785
-
786
- #unless defined? @paramdoc
787
- # @paramdoc = Hash.new { |hash,key|
788
- # if key.is_a?(String)
789
- # key = key.intern
790
- # end
791
- # if hash.include?(key)
792
- # hash[key]
793
- # else
794
- # "Param Documentation for %s not found" % key
795
- # end
796
- # }
797
- #end
798
1188
 
799
1189
  # set defalts
800
1190
  @noop = false
801
- @metaparams[:loglevel] = :notice
802
1191
  # keeping stats for the total number of changes, and how many were
803
1192
  # completely sync'ed
804
- # this isn't really sufficient either, because it adds lots of special cases
805
- # such as failed changes
1193
+ # this isn't really sufficient either, because it adds lots of special
1194
+ # cases such as failed changes
806
1195
  # it also doesn't distinguish between changes from the current transaction
807
1196
  # vs. changes over the process lifetime
808
1197
  @totalchanges = 0
809
1198
  @syncedchanges = 0
810
1199
  @failedchanges = 0
811
1200
 
1201
+ @inited = true
1202
+ end
1203
+
1204
+ # initialize the type instance
1205
+ def initialize(hash)
1206
+ unless defined? @inited
1207
+ self.initvars
1208
+ end
1209
+
1210
+ # If we got passed a transportable object, we just pull a bunch of info
1211
+ # directly from it.
1212
+ if hash.is_a?(Puppet::TransObject)
1213
+ #self[:name] = hash[:name]
1214
+ [:file, :line, :tags].each { |getter|
1215
+ if hash.respond_to?(getter)
1216
+ setter = getter.to_s + "="
1217
+ if val = hash.send(getter)
1218
+ self.send(setter, val)
1219
+ end
1220
+ end
1221
+ }
1222
+ hash = hash.to_hash
1223
+ end
1224
+
812
1225
  # Before anything else, set our parent if it was included
813
1226
  if hash.include?(:parent)
814
1227
  @parent = hash[:parent]
815
1228
  hash.delete(:parent)
816
1229
  end
817
1230
 
1231
+ # Convert all args to symbols
818
1232
  hash = self.argclean(hash)
819
1233
 
820
- # now get all of the arguments, in a specific order
821
- order = [self.class.namevar]
822
- order << [self.class.states.collect { |state| state.name },
823
- self.class.parameters,
824
- self.class.eachmetaparam { |param| param }].flatten.reject { |param|
825
- # we don't want our namevar in there multiple times
826
- param == self.class.namevar
827
- }
828
-
829
- order.flatten.each { |name|
1234
+ # Let's do the name first, because some things need to happen once
1235
+ # we have the name but before anything else
1236
+
1237
+ attrs = self.class.allattrs
1238
+ namevar = self.class.namevar
1239
+
1240
+ if hash.include?(namevar)
1241
+ #self.send(namevar.to_s + "=", hash[namevar])
1242
+ self[namevar] = hash[namevar]
1243
+ hash.delete(namevar)
1244
+ if attrs.include?(namevar)
1245
+ attrs.delete(namevar)
1246
+ else
1247
+ self.devfail "My namevar isn't a valid attribute...?"
1248
+ end
1249
+ else
1250
+ self.devfail "I was not passed a namevar"
1251
+ end
1252
+
1253
+ # The information to cache to disk. We have to do this after
1254
+ # the name is set because it uses the name and/or path, but before
1255
+ # everything else is set because the states need to be able to
1256
+ # retrieve their stored info.
1257
+ #@cache = Puppet::Storage.cache(self)
1258
+
1259
+ # This is all of our attributes except the namevar.
1260
+ attrs.each { |name|
830
1261
  if hash.include?(name)
831
1262
  begin
832
1263
  self[name] = hash[name]
833
1264
  rescue => detail
834
- raise Puppet::DevError.new(
835
- "Could not set %s on %s: %s" % [name, self.class.name, detail]
1265
+ self.devfail(
1266
+ "Could not set %s on %s: %s" %
1267
+ [name, self.class.name, detail]
836
1268
  )
837
1269
  end
838
1270
  hash.delete name
839
1271
  end
840
1272
  }
841
1273
 
1274
+ # While this could theoretically be set after all of the objects are
1275
+ # created, it seems to make more sense to set them immediately.
1276
+ self.setdefaults
1277
+
842
1278
  if hash.length > 0
843
1279
  self.debug hash.inspect
844
- raise Puppet::Error.new("Class %s does not accept argument(s) %s" %
1280
+ self.fail("Class %s does not accept argument(s) %s" %
845
1281
  [self.class.name, hash.keys.join(" ")])
846
1282
  end
847
1283
 
848
1284
  # add this object to the specific class's list of objects
849
1285
  #puts caller
850
1286
  self.class[self.name] = self
1287
+
1288
+ if self.respond_to?(:validate)
1289
+ self.validate
1290
+ end
1291
+ end
1292
+
1293
+ # Figure out of there are any objects we can automatically add as
1294
+ # dependencies.
1295
+ def autorequire
1296
+ self.class.eachautorequire { |type, block|
1297
+ # Ignore any types we can't find, although that would be a bit odd.
1298
+ next unless typeobj = Puppet.type(type)
1299
+
1300
+ # Retrieve the list of names from the block.
1301
+ next unless list = self.instance_eval(&block)
1302
+ unless list.is_a?(Array)
1303
+ list = [list]
1304
+ end
1305
+
1306
+ # Collect the current prereqs
1307
+ list.each { |dep|
1308
+ # Skip autorequires that we aren't managing
1309
+ next unless obj = typeobj[dep]
1310
+
1311
+ # Skip autorequires that we already require
1312
+ next if self.requires?(obj)
1313
+ self.info "Auto-requiring %s" % obj.name
1314
+
1315
+ self[:require] = [type, dep]
1316
+ }
1317
+
1318
+ #self.info reqs.inspect
1319
+ #self[:require] = reqs
1320
+ }
1321
+ end
1322
+
1323
+ # Set up all of our autorequires.
1324
+ def finish
1325
+ self.autorequire
1326
+
1327
+ # Scheduling has to be done when the whole config is instantiated, so
1328
+ # that file order doesn't matter in finding them.
1329
+ self.schedule
1330
+ end
1331
+
1332
+ # Return a cached value
1333
+ def cached(name)
1334
+ Puppet::Storage.cache(self)[name]
1335
+ #@cache[name] ||= nil
1336
+ end
1337
+
1338
+ # Cache a value
1339
+ def cache(name, value)
1340
+ Puppet::Storage.cache(self)[name] = value
1341
+ #@cache[name] = value
1342
+ end
1343
+
1344
+ # Look up the schedule and set it appropriately. This is done after
1345
+ # the instantiation phase, so that the schedule can be anywhere in the
1346
+ # file.
1347
+ def schedule
1348
+
1349
+ # If we've already set the schedule, then just move on
1350
+ return if self[:schedule].is_a?(Puppet.type(:schedule))
1351
+
1352
+ return unless self[:schedule]
1353
+
1354
+ # Schedules don't need to be scheduled
1355
+ #return if self.is_a?(Puppet.type(:schedule))
1356
+
1357
+ # Nor do components
1358
+ #return if self.is_a?(Puppet.type(:component))
1359
+
1360
+ if sched = Puppet.type(:schedule)[self[:schedule]]
1361
+ self[:schedule] = sched
1362
+ else
1363
+ self.fail "Could not find schedule %s" % self[:schedule]
1364
+ end
1365
+ # if self[:schedule]
1366
+ # elsif Puppet[:schedule] and ! Puppet[:ignoreschedules]
1367
+ # # We handle schedule defaults here mostly because otherwise things
1368
+ # # will behave very very erratically during testing.
1369
+ # if sched = Puppet.type(:schedule)[Puppet[:schedule]]
1370
+ # self[:schedule] = sched
1371
+ # else
1372
+ # self.fail "Could not find default schedule %s" % Puppet[:schedule]
1373
+ # end
1374
+ # else
1375
+ # # While it's unlikely we won't have any schedule (since there's a
1376
+ # # default), it's at least possible during testing
1377
+ # return true
1378
+ # end
1379
+ end
1380
+
1381
+ # Check whether we are scheduled to run right now or not.
1382
+ def scheduled?
1383
+ return true if Puppet[:ignoreschedules]
1384
+ return true unless schedule = self[:schedule]
1385
+
1386
+ # We use 'checked' here instead of 'synced' because otherwise we'll
1387
+ # end up checking most elements most times, because they will generally
1388
+ # have been synced a long time ago (e.g., a file only gets updated
1389
+ # once a month on the server and its schedule is daily; the last sync time
1390
+ # will have been a month ago, so we'd end up checking every run).
1391
+ return schedule.match?(self.cached(:checked).to_i)
1392
+ end
1393
+
1394
+ # Is the specified parameter set?
1395
+ def attrset?(type, attr)
1396
+ case type
1397
+ when :state: return @states.include?(attr)
1398
+ when :param: return @parameters.include?(attr)
1399
+ when :meta: return @metaparams.include?(attr)
1400
+ else
1401
+ self.devfail "Invalid set type %s" % [type]
1402
+ end
1403
+ end
1404
+
1405
+ # def set(name, value)
1406
+ # send(name.to_s + "=", value)
1407
+ # end
1408
+ #
1409
+ # def get(name)
1410
+ # send(name)
1411
+ # end
1412
+
1413
+ # For any parameters or states that have defaults and have not yet been
1414
+ # set, set them now.
1415
+ def setdefaults(*ary)
1416
+ self.class.eachattr(*ary) { |klass, type|
1417
+ # not many attributes will have defaults defined, so we short-circuit
1418
+ # those away
1419
+ next unless klass.method_defined?(:default)
1420
+ next if self.attrset?(type, klass.name)
1421
+
1422
+ obj = self.newattr(type, klass)
1423
+ #self.debug "defaulting %s to %s" % [obj.name, obj.default]
1424
+ obj.value = obj.default
1425
+ }
1426
+
851
1427
  end
852
1428
 
853
1429
  # Merge new information with an existing object, checking for conflicts
@@ -880,10 +1456,10 @@ class Type < Puppet::Element
880
1456
  # take the intersection
881
1457
  newvals = oldvals & value
882
1458
  if newvals.empty?
883
- raise Puppet::Error, "No common values for %s on %s(%s)" %
1459
+ self.fail "No common values for %s on %s(%s)" %
884
1460
  [param, self.class.name, self.name]
885
1461
  elsif newvals.length > 1
886
- raise Puppet::Error, "Too many values for %s on %s(%s)" %
1462
+ self.fail "Too many values for %s on %s(%s)" %
887
1463
  [param, self.class.name, self.name]
888
1464
  else
889
1465
  self.debug "Reduced old values %s and new values %s to %s" %
@@ -903,18 +1479,18 @@ class Type < Puppet::Element
903
1479
  unless defined? @name and @name
904
1480
  namevar = self.class.namevar
905
1481
  if self.class.validparameter?(namevar)
906
- @name = @parameters[namevar]
1482
+ @name = self[:name]
907
1483
  elsif self.class.validstate?(namevar)
908
1484
  @name = self.should(namevar)
909
1485
  else
910
- raise Puppet::DevError, "Could not find namevar %s for %s" %
1486
+ self.devfail "Could not find namevar %s for %s" %
911
1487
  [namevar, self.class.name]
912
1488
  end
913
1489
  end
914
1490
 
915
1491
  unless @name
916
- raise Puppet::DevError, "Could not find name %s for %s" %
917
- [namevar, self.class.name]
1492
+ self.devfail "Could not find namevar '%s' for %s" %
1493
+ [self.class.namevar, self.class.name]
918
1494
  end
919
1495
 
920
1496
  return @name
@@ -922,9 +1498,11 @@ class Type < Puppet::Element
922
1498
 
923
1499
  # fix any namevar => param translations
924
1500
  def argclean(hash)
925
- # we have to set the name of our object before anything else,
926
- # because it might be used in creating the other states
927
- hash = hash.dup
1501
+ # We have to set the name of our object before anything else,
1502
+ # because it might be used in creating the other states. We dup and
1503
+ # then convert to a hash here because TransObjects behave strangely
1504
+ # here.
1505
+ hash = hash.dup.to_hash
928
1506
 
929
1507
  if hash.include?(:parent)
930
1508
  hash.delete(:parent)
@@ -960,28 +1538,11 @@ class Type < Puppet::Element
960
1538
  def retrieve
961
1539
  # it's important to use the method here, as it follows the order
962
1540
  # in which they're defined in the object
963
- states.each { |state|
1541
+ states().each { |state|
964
1542
  state.retrieve
965
1543
  }
966
1544
  end
967
1545
 
968
- # sync the changes to disk, and return the events generated by the changes
969
- # FIXME this method is essentially obviated, but it's still used by tests
970
- # and i don't feel like fixing it yet
971
- def sync
972
- #raise Puppet::DevError, "Type#sync called"
973
- events = self.collect { |child|
974
- child.sync
975
- }.reject { |event|
976
- ! (event.is_a?(Symbol) or event.is_a?(String))
977
- }.flatten
978
-
979
- #Puppet.notice "got events %s" % events.inspect
980
-
981
- Puppet::Metric.addevents(self.class,self,events)
982
- return events
983
- end
984
-
985
1546
  # convert to a string
986
1547
  def to_s
987
1548
  self.name
@@ -1001,12 +1562,42 @@ class Type < Puppet::Element
1001
1562
  end
1002
1563
  end
1003
1564
 
1565
+ # Retrieve the changes associated with all of the states.
1566
+ def statechanges
1567
+ # If we are changing the existence of the object, then none of
1568
+ # the other states matter.
1569
+ if @states.include?(:ensure) and ! @states[:ensure].insync?
1570
+ #self.info "ensuring %s from %s" %
1571
+ # [@states[:ensure].should, @states[:ensure].is]
1572
+ return [Puppet::StateChange.new(@states[:ensure])]
1573
+ # Else, if the 'ensure' state is correctly absent, then do
1574
+ # nothing
1575
+ elsif @states.include?(:ensure) and @states[:ensure].is == :absent
1576
+ #self.info "Object is correctly absent"
1577
+ return []
1578
+ else
1579
+ #if @states.include?(:ensure)
1580
+ # self.info "ensure: Is: %s, Should: %s" %
1581
+ # [@states[:ensure].is, @states[:ensure].should]
1582
+ #else
1583
+ # self.info "no ensure state"
1584
+ #end
1585
+ return states().find_all { |state|
1586
+ ! state.insync?
1587
+ }.collect { |state|
1588
+ Puppet::StateChange.new(state)
1589
+ }
1590
+ end
1591
+ end
1592
+
1004
1593
  # this method is responsible for collecting state changes
1005
1594
  # we always descend into the children before we evaluate our current
1006
1595
  # states
1007
1596
  # this returns any changes resulting from testing, thus 'collect'
1008
1597
  # rather than 'each'
1009
1598
  def evaluate
1599
+ now = Time.now
1600
+
1010
1601
  #Puppet.err "Evaluating %s" % self.path.join(":")
1011
1602
  unless defined? @evalcount
1012
1603
  self.err "No evalcount defined on '%s' of type '%s'" %
@@ -1040,11 +1631,7 @@ class Type < Puppet::Element
1040
1631
 
1041
1632
  # states() is a private method, returning an ordered list
1042
1633
  unless self.class.depthfirst?
1043
- changes << states().find_all { |state|
1044
- ! state.insync?
1045
- }.collect { |state|
1046
- Puppet::StateChange.new(state)
1047
- }
1634
+ changes += statechanges()
1048
1635
  end
1049
1636
 
1050
1637
  if changes.length > 0
@@ -1054,7 +1641,9 @@ class Type < Puppet::Element
1054
1641
  #end
1055
1642
 
1056
1643
  changes << @children.collect { |child|
1057
- child.evaluate
1644
+ ch = child.evaluate
1645
+ child.cache(:checked, now)
1646
+ ch
1058
1647
  }
1059
1648
  #unless self.class.depthfirst?
1060
1649
  # changes << self.collect { |child|
@@ -1068,11 +1657,7 @@ class Type < Puppet::Element
1068
1657
  #}
1069
1658
 
1070
1659
  if self.class.depthfirst?
1071
- changes << states().find_all { |state|
1072
- ! state.insync?
1073
- }.collect { |state|
1074
- Puppet::StateChange.new(state)
1075
- }
1660
+ changes += statechanges()
1076
1661
  end
1077
1662
 
1078
1663
  changes.flatten!
@@ -1086,6 +1671,7 @@ class Type < Puppet::Element
1086
1671
  # self.debug "change: %s" % change.state.name
1087
1672
  #}
1088
1673
  end
1674
+ self.cache(:checked, now)
1089
1675
  return changes.flatten
1090
1676
  end
1091
1677
 
@@ -1095,10 +1681,16 @@ class Type < Puppet::Element
1095
1681
  def insync?
1096
1682
  insync = true
1097
1683
 
1684
+ if state = @states[:ensure]
1685
+ if state.insync? and state.should == :absent
1686
+ return true
1687
+ end
1688
+ end
1689
+
1098
1690
  states.each { |state|
1099
1691
  unless state.insync?
1100
1692
  self.debug("%s is not in sync: %s vs %s" %
1101
- [state, state.is, state.should])
1693
+ [state, state.is.inspect, state.should.inspect])
1102
1694
  insync = false
1103
1695
  end
1104
1696
  }
@@ -1110,95 +1702,57 @@ class Type < Puppet::Element
1110
1702
  # Meta-parameter methods: These methods deal with the results
1111
1703
  # of specifying metaparameters
1112
1704
 
1113
- def self.eachmetaparam
1114
- @@metaparams.each { |param|
1115
- yield param
1116
- }
1117
- end
1118
-
1119
- # This just marks states that we definitely want to retrieve values
1120
- # on. There is currently no way to uncheck a parameter.
1121
- def metacheck=(args)
1122
- unless args.is_a?(Array)
1123
- args = [args]
1124
- end
1125
-
1126
- # these are states that we might not have 'should'
1127
- # values for but we want to retrieve 'is' values for anyway
1128
- args.each { |state|
1129
- unless state.is_a?(Symbol)
1130
- state = state.intern
1131
- end
1132
- next if @states.include?(state)
1133
-
1134
- stateklass = nil
1135
- self.newstate(state)
1136
- }
1705
+ def self.metaparams
1706
+ @@metaparams.collect { |param| param.name }
1137
1707
  end
1138
1708
 
1139
1709
  # Is the parameter in question a meta-parameter?
1140
1710
  def self.metaparam?(param)
1141
- @@metaparams.include?(param)
1711
+ @@metaparamhash.include?(param)
1142
1712
  end
1143
1713
 
1144
- # for each object we require, subscribe to all events that it
1145
- # generates
1146
- # we might reduce the level of subscription eventually, but for now...
1147
- def metarequire=(requires)
1148
- self.handledepends(requires, :NONE, nil)
1149
- end
1150
-
1151
- # for each object we require, subscribe to all events that it
1152
- # generates
1153
- # we might reduce the level of subscription eventually, but for now...
1154
- def metasubscribe=(requires)
1155
- self.handledepends(requires, :ALL_EVENTS, :refresh)
1156
- end
1714
+ # Subscription and relationship methods
1157
1715
 
1158
- def metanoop=(noop)
1159
- if noop == "true" or noop == true
1160
- @noop = true
1161
- elsif noop == "false" or noop == false
1162
- @noop = false
1163
- else
1164
- raise Puppet::Error.new("Invalid noop value '%s'" % noop)
1165
- end
1166
- end
1716
+ #def addcallback(object, event, method)
1717
+ # @callbacks[object][event] = method
1718
+ #end
1167
1719
 
1168
- # Currently nonfunctional
1169
- def metaonerror=(response)
1170
- self.debug("Would have called metaonerror")
1171
- @onerror = response
1720
+ # Build all of the dependencies for all of the different types. This is called
1721
+ # after all of the objects are instantiated, so that we don't depend on
1722
+ # file order. If we didn't use this (and instead just checked dependencies
1723
+ # as we came across them), any required object would have to come before the
1724
+ # requiring object in the file(s).
1725
+ def self.mkdepends
1726
+ @types.each { |name, type|
1727
+ type.each { |obj|
1728
+ obj.builddepends
1729
+ }
1730
+ }
1172
1731
  end
1173
1732
 
1174
- # Currently nonfunctional
1175
- def metaschedule=(schedule)
1176
- @schedule = schedule
1733
+ # The per-type version of dependency building. This actually goes through
1734
+ # all of the objects themselves and builds deps.
1735
+ def self.builddepends
1736
+ return unless defined? @objects
1737
+ @objects.each { |name, obj|
1738
+ obj.builddepends
1739
+ }
1177
1740
  end
1178
1741
 
1179
- # Determines what our objects log at. Defaults to :notice.
1180
- def metaloglevel=(loglevel)
1181
- if loglevel.is_a?(String)
1182
- loglevel = loglevel.intern
1742
+ # Build the dependencies associated with an individual object.
1743
+ def builddepends
1744
+ # Handle the requires
1745
+ if self[:require]
1746
+ self.handledepends(self[:require], :NONE, nil)
1183
1747
  end
1184
- if loglevel == :verbose
1185
- loglevel = :info
1186
- end
1187
1748
 
1188
- if Puppet::Log.validlevel?(loglevel)
1189
- @metaparams[:loglevel] = loglevel
1190
- else
1191
- raise Puppet::Error.new("Invalid loglevel '%s'" % loglevel)
1749
+ # And the subscriptions
1750
+ if self[:subscribe]
1751
+ self.handledepends(self[:subscribe], :ALL_EVENTS, :refresh)
1192
1752
  end
1193
1753
  end
1194
1754
 
1195
- # Subscription and relationship methods
1196
-
1197
- #def addcallback(object, event, method)
1198
- # @callbacks[object][event] = method
1199
- #end
1200
-
1201
- # return all objects subscribed to the current object
1755
+ # return all objects that we depend on
1202
1756
  def eachdependency
1203
1757
  Puppet::Event::Subscription.dependencies(self).each { |dep|
1204
1758
  yield dep.source
@@ -1225,11 +1779,11 @@ class Type < Puppet::Element
1225
1779
  object = nil
1226
1780
  tname = rname[0]
1227
1781
  unless type = Puppet::Type.type(tname)
1228
- raise Puppet::Error, "Could not find type %s" % tname
1782
+ self.fail "Could not find type %s" % tname.inspect
1229
1783
  end
1230
1784
  name = rname[1]
1231
1785
  unless object = type[name]
1232
- raise Puppet::Error, "Could not retrieve object '%s' of type '%s'" %
1786
+ self.fail "Could not retrieve object '%s' of type '%s'" %
1233
1787
  [name,type]
1234
1788
  end
1235
1789
  self.debug("subscribes to %s" % [object])
@@ -1253,10 +1807,6 @@ class Type < Puppet::Element
1253
1807
  subargs[:callback] = method
1254
1808
  end
1255
1809
  Puppet::Event::Subscription.new(subargs)
1256
- #if self.respond_to?(method)
1257
- # self.addcallback(object, event, method)
1258
- #end
1259
- #object.addnotify(self)
1260
1810
  }
1261
1811
  end
1262
1812
 
@@ -1270,6 +1820,18 @@ class Type < Puppet::Element
1270
1820
  end
1271
1821
  end
1272
1822
 
1823
+ def requires?(object)
1824
+ req = false
1825
+ self.eachdependency { |dep|
1826
+ if dep == object
1827
+ req = true
1828
+ break
1829
+ end
1830
+ }
1831
+
1832
+ return req
1833
+ end
1834
+
1273
1835
  def subscribe(hash)
1274
1836
  hash[:source] = self
1275
1837
  Puppet::Event::Subscription.new(hash)
@@ -1291,15 +1853,6 @@ class Type < Puppet::Element
1291
1853
  }
1292
1854
  end
1293
1855
 
1294
- # return all of the subscriptions to a given event
1295
- #def subscribers?(event)
1296
- # Puppet::Event::Subscription.subscriptions(self).find_all { |sub|
1297
- # sub.match?(event)
1298
- # }.collect { |sub|
1299
- # sub.target
1300
- # }
1301
- #end
1302
-
1303
1856
  # we've received an event
1304
1857
  # we only support local events right now, so we can pass actual
1305
1858
  # objects around, including the transaction object
@@ -1327,10 +1880,239 @@ class Type < Puppet::Element
1327
1880
 
1328
1881
  # Documentation methods
1329
1882
  def self.paramdoc(param)
1330
- @paramdoc[param]
1883
+ @paramhash[param].doc
1331
1884
  end
1332
1885
  def self.metaparamdoc(metaparam)
1333
- @@metaparamdoc[metaparam]
1886
+ @@metaparamhash[metaparam].doc
1887
+ end
1888
+
1889
+ # Add all of the meta parameters.
1890
+ #newmetaparam(:onerror) do
1891
+ # desc "How to handle errors -- roll back innermost
1892
+ # transaction, roll back entire transaction, ignore, etc. Currently
1893
+ # non-functional."
1894
+ #end
1895
+
1896
+ newmetaparam(:noop) do
1897
+ desc "Boolean flag indicating whether work should actually
1898
+ be done. *true*/**false**"
1899
+ munge do |noop|
1900
+ if noop == "true" or noop == true
1901
+ return true
1902
+ elsif noop == "false" or noop == false
1903
+ return false
1904
+ else
1905
+ self.fail("Invalid noop value '%s'" % noop)
1906
+ end
1907
+ end
1908
+ end
1909
+
1910
+ newmetaparam(:schedule) do
1911
+ desc "On what schedule the object should be managed. You must create a
1912
+ schedule_ object, and then reference the name of that object to use
1913
+ that for your schedule::
1914
+
1915
+ schedule { daily:
1916
+ period => daily,
1917
+ range => \"2-4\"
1918
+ }
1919
+
1920
+ exec { \"/usr/bin/apt-get update\":
1921
+ schedule => daily
1922
+ }
1923
+
1924
+ The creation of the schedule object does not need to appear in the
1925
+ configuration before objects that use it."
1926
+
1927
+ munge do |name|
1928
+ if schedule = Puppet.type(:schedule)[name]
1929
+ return schedule
1930
+ else
1931
+ return name
1932
+ end
1933
+ end
1934
+ end
1935
+
1936
+ newmetaparam(:check) do
1937
+ desc "States which should have their values retrieved
1938
+ but which should not actually be modified. This is currently used
1939
+ internally, but will eventually be used for querying, so that you
1940
+ could specify that you wanted to check the install state of all
1941
+ packages, and then query the Puppet client daemon to get reports
1942
+ on all packages."
1943
+
1944
+ munge do |args|
1945
+ unless args.is_a?(Array)
1946
+ args = [args]
1947
+ end
1948
+
1949
+ unless defined? @parent
1950
+ self.devfail "No parent for %s, %s?" %
1951
+ [self.class, self.name]
1952
+ end
1953
+
1954
+ args.each { |state|
1955
+ unless state.is_a?(Symbol)
1956
+ state = state.intern
1957
+ end
1958
+ next if @parent.statedefined?(state)
1959
+
1960
+ @parent.newstate(state)
1961
+ }
1962
+ end
1963
+ end
1964
+ # For each object we require, subscribe to all events that it generates. We
1965
+ # might reduce the level of subscription eventually, but for now...
1966
+ newmetaparam(:require) do
1967
+ desc "One or more objects that this object depends on.
1968
+ This is used purely for guaranteeing that changes to required objects
1969
+ happen before the dependent object. For instance::
1970
+
1971
+ # Create the destination directory before you copy things down
1972
+ file { \"/usr/local/scripts\":
1973
+ ensure => directory
1974
+ }
1975
+
1976
+ file { \"/usr/local/scripts/myscript\":
1977
+ source => \"puppet://server/module/myscript\",
1978
+ mode => 755,
1979
+ require => file[\"/usr/local/scripts\"]
1980
+ }
1981
+
1982
+ Note that Puppet will autorequire everything that it can, and
1983
+ there are hooks in place so that it's easy for elements to add new
1984
+ ways to autorequire objects, so if you think Puppet could be
1985
+ smarter here, let us know.
1986
+
1987
+ In fact, the above code was redundant -- Puppet will autorequire
1988
+ any parent directories that are being managed; it will
1989
+ automatically realize that the parent directory should be created
1990
+ before the script is pulled down.
1991
+
1992
+ Currently, exec_ elements will autorequire their CWD (if it is
1993
+ specified) plus any fully qualified paths that appear in the
1994
+ command. For instance, if you had an ``exec`` command that ran
1995
+ the ``myscript`` mentioned above, the above code that pulls the
1996
+ file down would be automatically listed as a requirement to the
1997
+ ``exec`` code, so that you would always be running againts the
1998
+ most recent version.
1999
+ "
2000
+
2001
+ # Take whatever dependencies currently exist and add these.
2002
+ # Note that this probably doesn't behave correctly with unsubscribe.
2003
+ munge do |requires|
2004
+ # We need to be two arrays deep...
2005
+ unless requires.is_a?(Array)
2006
+ requires = [requires]
2007
+ end
2008
+ unless requires[0].is_a?(Array)
2009
+ requires = [requires]
2010
+ end
2011
+ if values = @parent[:require]
2012
+ requires = values + requires
2013
+ end
2014
+ requires
2015
+ #p @parent[:require]
2016
+ #@parent.handledepends(requires, :NONE, nil)
2017
+ end
2018
+ end
2019
+
2020
+ # For each object we require, subscribe to all events that it generates.
2021
+ # We might reduce the level of subscription eventually, but for now...
2022
+ newmetaparam(:subscribe) do
2023
+ desc "One or more objects that this object depends on. Changes in the
2024
+ subscribed to objects result in the dependent objects being
2025
+ refreshed (e.g., a service will get restarted). For instance::
2026
+
2027
+ class nagios {
2028
+ file { \"/etc/nagios/nagios.conf\":
2029
+ source => \"puppet://server/module/nagios.conf\",
2030
+ alias => nagconf # just to make things easier for me
2031
+ }
2032
+
2033
+ service { nagios:
2034
+ running => true,
2035
+ require => file[nagconf]
2036
+ }
2037
+ }
2038
+ "
2039
+
2040
+ munge do |requires|
2041
+ if values = @parent[:subscribe]
2042
+ requires = values + requires
2043
+ end
2044
+ requires
2045
+ # @parent.handledepends(requires, :ALL_EVENTS, :refresh)
2046
+ end
2047
+ end
2048
+
2049
+ newmetaparam(:loglevel) do
2050
+ desc "Sets the level that information will be logged:
2051
+ debug, info, verbose, notice, warning, err, alert, emerg or crit.
2052
+ The log levels have the biggest impact when logs are sent to
2053
+ syslog (which is currently the default)."
2054
+ defaultto :notice
2055
+
2056
+ validate do |loglevel|
2057
+ if loglevel.is_a?(String)
2058
+ loglevel = loglevel.intern
2059
+ end
2060
+ unless Puppet::Log.validlevel?(loglevel)
2061
+ self.fail "Invalid log level %s" % loglevel
2062
+ end
2063
+ end
2064
+
2065
+ munge do |loglevel|
2066
+ if loglevel.is_a?(String)
2067
+ loglevel = loglevel.intern
2068
+ end
2069
+ if loglevel == :verbose
2070
+ loglevel = :info
2071
+ end
2072
+ loglevel
2073
+ end
2074
+ end
2075
+
2076
+ newmetaparam(:alias) do
2077
+ desc "Creates an alias for the object. This simplifies lookup of the
2078
+ object so is useful in the language. It is especially useful when
2079
+ you are creating long commands using exec or when many different
2080
+ systems call a given package_ different names::
2081
+
2082
+
2083
+ file { \"/usr/local/scripts/myscript\":
2084
+ source => \"puppet://server/module/myscript\",
2085
+ mode => 755,
2086
+ alias => myscript
2087
+ }
2088
+
2089
+ exec { \"/usr/local/scripts/myscript\":
2090
+ require => file[myscript]
2091
+ }
2092
+
2093
+ Again, this is somewhat redundant, since any sane person would
2094
+ just use a variable (unless the two statements were in different
2095
+ scopes), and Puppet will autorequire the script anyway, but it
2096
+ gets the point across."
2097
+
2098
+ munge do |aliases|
2099
+ unless aliases.is_a?(Array)
2100
+ aliases = [aliases]
2101
+ end
2102
+ @parent.info "Adding aliases %s" % aliases.join(", ")
2103
+ aliases.each do |other|
2104
+ if obj = @parent.class[other]
2105
+ unless obj == @parent
2106
+ self.fail(
2107
+ "%s an not create alias %s: object already exists" %
2108
+ [@parent.name, other]
2109
+ )
2110
+ end
2111
+ next
2112
+ end
2113
+ @parent.class.alias(other, @parent)
2114
+ end
2115
+ end
1334
2116
  end
1335
2117
  end # Puppet::Type
1336
2118
  end
@@ -1343,12 +2125,11 @@ require 'puppet/type/group'
1343
2125
  require 'puppet/type/package'
1344
2126
  require 'puppet/type/pfile'
1345
2127
  require 'puppet/type/pfilebucket'
2128
+ require 'puppet/type/schedule'
1346
2129
  require 'puppet/type/service'
1347
2130
  require 'puppet/type/symlink'
1348
2131
  require 'puppet/type/user'
1349
2132
  require 'puppet/type/tidy'
1350
- #require 'puppet/type/typegen'
1351
- #require 'puppet/type/typegen/filetype'
1352
- #require 'puppet/type/typegen/filerecord'
2133
+ require 'puppet/type/parsedtype'
1353
2134
 
1354
- # $Id: type.rb 742 2005-11-16 17:12:11Z luke $
2135
+ # $Id: type.rb 886 2006-02-08 17:45:26Z luke $