puppet 0.23.1 → 0.23.2

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 (55) hide show
  1. data/CHANGELOG +31 -0
  2. data/bin/puppetd +2 -1
  3. data/conf/redhat/puppet.spec +9 -6
  4. data/conf/redhat/server.init +4 -5
  5. data/examples/code/mac_dscl.pp +28 -0
  6. data/examples/code/mac_dscl_revert.pp +26 -0
  7. data/examples/code/mac_netinfo.pp +5 -0
  8. data/examples/code/mac_pkgdmg.pp +7 -0
  9. data/ext/puppet-test +69 -2
  10. data/lib/puppet.rb +2 -2
  11. data/lib/puppet/configuration.rb +5 -1
  12. data/lib/puppet/network/server/mongrel.rb +3 -3
  13. data/lib/puppet/parser/ast.rb +2 -2
  14. data/lib/puppet/parser/ast/component.rb +3 -3
  15. data/lib/puppet/parser/ast/node.rb +2 -2
  16. data/lib/puppet/parser/collector.rb +2 -2
  17. data/lib/puppet/parser/interpreter.rb +38 -215
  18. data/lib/puppet/parser/parser.rb +11 -228
  19. data/lib/puppet/parser/parser_support.rb +447 -0
  20. data/lib/puppet/parser/resource/param.rb +2 -2
  21. data/lib/puppet/provider.rb +5 -3
  22. data/lib/puppet/provider/cron/crontab.rb +22 -9
  23. data/lib/puppet/provider/group/directoryservice.rb +23 -0
  24. data/lib/puppet/provider/interface/redhat.rb +251 -0
  25. data/lib/puppet/provider/interface/sunos.rb +116 -0
  26. data/lib/puppet/provider/mount.rb +4 -1
  27. data/lib/puppet/provider/nameservice/directoryservice.rb +341 -0
  28. data/lib/puppet/provider/package/dpkg.rb +2 -2
  29. data/lib/puppet/provider/package/openbsd.rb +2 -2
  30. data/lib/puppet/provider/package/rpm.rb +2 -4
  31. data/lib/puppet/provider/package/sun.rb +2 -2
  32. data/lib/puppet/provider/parsedfile.rb +32 -29
  33. data/lib/puppet/provider/user/directoryservice.rb +116 -0
  34. data/lib/puppet/rails/host.rb +1 -1
  35. data/lib/puppet/reference/configuration.rb +7 -4
  36. data/lib/puppet/type/interface.rb +57 -0
  37. data/lib/puppet/type/pfile/group.rb +2 -2
  38. data/lib/puppet/util/config.rb +10 -3
  39. data/lib/puppet/util/fileparsing.rb +2 -2
  40. data/test/language/ast/hostclass.rb +1 -17
  41. data/test/language/interpreter.rb +18 -388
  42. data/test/language/node.rb +8 -8
  43. data/test/language/parser.rb +444 -45
  44. data/test/lib/puppettest/parsertesting.rb +2 -2
  45. data/test/lib/puppettest/support/collection.rb +2 -2
  46. data/test/network/server/mongrel_test.rb +24 -3
  47. data/test/rails/collection.rb +34 -1
  48. data/test/ral/providers/cron/crontab.rb +198 -40
  49. data/test/ral/providers/mount/parsed.rb +69 -46
  50. data/test/ral/providers/parsedfile.rb +20 -28
  51. data/test/ral/types/cron.rb +20 -24
  52. data/test/ral/types/interface.rb +40 -0
  53. data/test/ral/types/package.rb +6 -2
  54. data/test/util/config.rb +106 -30
  55. metadata +14 -2
@@ -16,6 +16,9 @@ module Puppet::Provider::Mount
16
16
  end
17
17
  args << @resource[:name]
18
18
 
19
+ if respond_to?(:flush)
20
+ flush
21
+ end
19
22
  mountcmd(*args)
20
23
  end
21
24
 
@@ -48,4 +51,4 @@ module Puppet::Provider::Mount
48
51
  end
49
52
  end
50
53
 
51
- # $Id: mount.rb 2707 2007-07-18 20:40:11Z luke $
54
+ # $Id: mount.rb 2745 2007-08-05 17:49:23Z luke $
@@ -0,0 +1,341 @@
1
+ # Created by Jeff McCune on 2007-07-22
2
+ # Copyright (c) 2007. All rights reserved.
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation (version 2 of the License)
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ # You should have received a copy of the GNU General Public License
12
+ # along with this program; if not, write to the Free Software
13
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston MA 02110-1301 USA
14
+
15
+ require 'puppet'
16
+ require 'puppet/provider/nameservice'
17
+
18
+ class Puppet::Provider::NameService
19
+ class DirectoryService < Puppet::Provider::NameService
20
+ # JJM: Dive into the eigenclass
21
+ class << self
22
+ # JJM: This allows us to pass information when calling
23
+ # Puppet::Type.type
24
+ # e.g. Puppet::Type.type(:user).provide :directoryservice, :ds_path => "Users"
25
+ # This is referenced in the get_ds_path class method
26
+ attr_writer :ds_path
27
+ end
28
+
29
+ # JJM 2007-07-24: Not yet sure what initvars() does. I saw it in netinfo.rb
30
+ # I do know, however, that it makes methods "work" =)
31
+ # e.g. addcmd isn't available if this method call isn't present.
32
+ #
33
+ # JJM: Also, where this method is defined seems to impact the visibility
34
+ # of methods. If I put initvars after commands, confine and defaultfor,
35
+ # then getinfo is called from the parent class, not this class.
36
+ initvars()
37
+
38
+ commands :dscl => "/usr/bin/dscl"
39
+ confine :operatingsystem => :darwin
40
+ # JJM FIXME: This will need to be the default around October 2007.
41
+ # defaultfor :operatingsystem => :darwin
42
+
43
+
44
+ # JJM 2007-07-25: This map is used to map NameService attributes to their
45
+ # corresponding DirectoryService attribute names.
46
+ # See: http://images.apple.com/server/docs/Open_Directory_v10.4.pdf
47
+ # JJM: Note, this is de-coupled from the Puppet::Type, and must
48
+ # be actively maintained. There may also be collisions with different
49
+ # types (Users, Groups, Mounts, Hosts, etc...)
50
+ @@ds_to_ns_attribute_map = {
51
+ 'RecordName' => :name,
52
+ 'PrimaryGroupID' => :gid,
53
+ 'NFSHomeDirectory' => :home,
54
+ 'UserShell' => :shell,
55
+ 'UniqueID' => :uid,
56
+ 'RealName' => :comment,
57
+ 'Password' => :password,
58
+ }
59
+ # JJM The same table as above, inverted.
60
+ @@ns_to_ds_attribute_map = {
61
+ :name => 'RecordName',
62
+ :gid => 'PrimaryGroupID',
63
+ :home => 'NFSHomeDirectory',
64
+ :shell => 'UserShell',
65
+ :uid => 'UniqueID',
66
+ :comment => 'RealName',
67
+ :password => 'Password',
68
+ }
69
+
70
+ def self.instances
71
+ # JJM Class method that provides an array of instance objects of this
72
+ # type.
73
+
74
+ # JJM: Properties are dependent on the Puppet::Type we're managine.
75
+ type_property_array = [:name] + @resource_type.validproperties
76
+ # JJM: No sense reporting the password. It's hashed.
77
+ type_property_array.delete(:password) if type_property_array.include? :password
78
+
79
+ # Create a new instance of this Puppet::Type for each object present
80
+ # on the system.
81
+ list_all_present.collect do |name_string|
82
+ self.new(single_report(name_string, *type_property_array))
83
+ end
84
+ end
85
+
86
+ def self.get_ds_path
87
+ # JJM: 2007-07-24 This method dynamically returns the DS path we're concerned with.
88
+ # For example, if we're working with an user type, this will be /Users
89
+ # with a group type, this will be /Groups.
90
+ # @ds_path is an attribute of the class itself.
91
+ if defined? @ds_path
92
+ return @ds_path
93
+ else
94
+ # JJM: "Users" or "Groups" etc ... (Based on the Puppet::Type)
95
+ # Remember this is a class method, so self.class is Class
96
+ # Also, @resource_type seems to be the reference to the
97
+ # Puppet::Type this class object is providing for.
98
+ return @resource_type.name.to_s.capitalize + "s"
99
+ end
100
+ end
101
+
102
+ def self.list_all_present
103
+ # JJM: List all objects of this Puppet::Type already present on the system.
104
+ begin
105
+ dscl_output = execute(get_exec_preamble("-list"))
106
+ rescue Puppet::ExecutionFailure => detail
107
+ raise Puppet::Error, "Could not get %s list from DirectoryService" % [ @resource_type.name.to_s ]
108
+ end
109
+ return dscl_output.split("\n")
110
+ end
111
+
112
+ def self.single_report(resource_name, *type_properties)
113
+ # JJM 2007-07-24:
114
+ # Given a the name of an object and a list of properties of that
115
+ # object, return all property values in a hash.
116
+ #
117
+ # This class method returns nil if the object doesn't exist
118
+ # Otherwise, it returns a hash of the object properties.
119
+
120
+ all_present_str_array = list_all_present()
121
+
122
+ # JJM: Return nil if the named object isn't present.
123
+ return nil unless all_present_str_array.include? resource_name
124
+
125
+ dscl_vector = get_exec_preamble("-read", resource_name)
126
+ begin
127
+ dscl_output = execute(dscl_vector)
128
+ rescue Puppet::ExecutionFailure => detail
129
+ raise Puppet::Error, "Could not get report. command execution failed."
130
+ end
131
+
132
+ # JJM: We need a new hash to return back to our caller.
133
+ attribute_hash = Hash.new
134
+
135
+ # JJM: First, the output string goes into an array.
136
+ # Then, the each array element is split
137
+ # If you want to figure out what this is doing, I suggest
138
+ # ruby-debug, and stepping through it.
139
+ dscl_output.split("\n").each do |line|
140
+ # JJM: Split the attribute name and the list of values.
141
+ ds_attribute, ds_values_string = line.split(':')
142
+
143
+ # JJM: skip this attribute line if the Puppet::Type doesn't care about it.
144
+ next unless (@@ds_to_ns_attribute_map.keys.include?(ds_attribute) \
145
+ and type_properties.include? @@ds_to_ns_attribute_map[ds_attribute])
146
+
147
+ # JJM: We asked dscl to output url encoded values so we're able
148
+ # to machine parse on whitespace. We need to urldecode:
149
+ # " Jeff%20McCune John%20Doe " => ["Jeff McCune", "John Doe"]
150
+ ds_value_array = ds_values_string.scan(/[^\s]+/).collect do |v|
151
+ url_decoded_value = CGI::unescape v
152
+ if url_decoded_value =~ /^[-0-9]+$/
153
+ url_decoded_value.to_i
154
+ else
155
+ url_decoded_value
156
+ end
157
+ end
158
+
159
+ # JJM: Finally, we're able to build up our attribute hash.
160
+ # Remember, the hash is keyed by NameService attribute names,
161
+ # not DirectoryService attribute names.
162
+ # NOTE: We're also sort of cheating here... DirectoryService
163
+ # is robust enough to allow multiple values for almost every
164
+ # attribute in the system. Traditional NameService things
165
+ # really don't handle this case, so we'll always pull thet first
166
+ # value returned from DirectoryService.
167
+ # THERE MAY BE AN ORDERING ISSUE HERE, but I think it's ok...
168
+ attribute_hash[@@ds_to_ns_attribute_map[ds_attribute]] = ds_value_array[0]
169
+ end
170
+ return attribute_hash
171
+ end
172
+
173
+ def self.get_exec_preamble(ds_action, resource_name = nil)
174
+ # JJM 2007-07-24
175
+ # DSCL commands are often repetitive and contain the same positional
176
+ # arguments over and over. See http://developer.apple.com/documentation/Porting/Conceptual/PortingUnix/additionalfeatures/chapter_10_section_9.html
177
+ # for an example of what I mean.
178
+ # This method spits out proper DSCL commands for us.
179
+ # We EXPECT name to be @resource[:name] when called from an instance object.
180
+
181
+ # JJM: With dscl, the domain "/" is always the default local domain.
182
+ # The domain /Search will search all domains, and you may
183
+ # get at specific domains with /LDAPv3/server1.foobar.com,
184
+ # /LDAPv3/server2.foobar.com, etc...
185
+ command_vector = [ command(:dscl), "-url", "/" ]
186
+ # JJM: The actual action to perform. See "man dscl"
187
+ # Common actiosn: -create, -delete, -merge, -append, -passwd
188
+ command_vector << ds_action
189
+ # JJM: get_ds_path will spit back "Users" or "Groups",
190
+ # etc... Depending on the Puppet::Type of our self.
191
+ if resource_name
192
+ command_vector << "/%s/%s" % [ get_ds_path, resource_name ]
193
+ else
194
+ command_vector << "/%s" % [ get_ds_path ]
195
+ end
196
+ # JJM: This returns most of the preamble of the command.
197
+ # e.g. 'dscl / -create /Users/mccune'
198
+ return command_vector
199
+ end
200
+
201
+ def ensure=(ensure_value)
202
+ super
203
+ # JJM: Modeled after nameservice/netinfo.rb, we need to
204
+ # loop over all valid properties for the type we're managing
205
+ # and call the method which sets that property value
206
+ # Like netinfo, dscl can't create everything at once, afaik.
207
+ if ensure_value == :present
208
+ @resource.class.validproperties.each do |name|
209
+ next if name == :ensure
210
+ next unless val = @resource.should(name) || autogen(name)
211
+ # JJM: This calls the method.
212
+ self.send(name.to_s + "=", val)
213
+ end
214
+ end
215
+ end
216
+
217
+ def password=(passphrase)
218
+ # JJM: Setting the password is a special case. We don't just
219
+ # set the attribute because we need to update the password
220
+ # databases.
221
+ # FIRST, make sure the AuthenticationAuthority is ;ShadowHash; If
222
+ # we don't do this, we don't get a shadow hash account. ("Obviously...")
223
+ dscl_vector = self.class.get_exec_preamble("-create", @resource[:name])
224
+ dscl_vector << "AuthenticationAuthority" << ";ShadowHash;"
225
+ begin
226
+ dscl_output = execute(dscl_vector)
227
+ rescue Puppet::ExecutionFailure => detail
228
+ raise Puppet::Error, "Could not set AuthenticationAuthority."
229
+ end
230
+
231
+ # JJM: Second, we need to actually set the password. dscl does
232
+ # some magic, creating the proper hash for us based on the
233
+ # AuthenticationAuthority attribute, set above.
234
+ dscl_vector = self.class.get_exec_preamble("-passwd", @resource[:name])
235
+ dscl_vector << passphrase
236
+ # JJM: Should we not log the password string? This may be a security
237
+ # risk...
238
+ begin
239
+ dscl_output = execute(dscl_vector)
240
+ rescue Puppet::ExecutionFailure => detail
241
+ raise Puppet::Error, "Could not set password using command vector: %{dscl_vector.inspect}"
242
+ end
243
+ end
244
+
245
+ # JJM: nameservice.rb defines methods for each attribute of the type.
246
+ # We implement these methods here, by implementing get() and set()
247
+ # See the resource_type= method defined in nameservice.rb
248
+ # I'm not sure what the implications are of doing things this way.
249
+ # It was a bit difficult to sort out what was happening in my head,
250
+ # but ruby-debug makes this process much more transparent.
251
+ #
252
+ def set(property, value)
253
+ # JJM: As it turns out, the set method defined in our parent class
254
+ # is fine. It just calls the modifycmd() method, which
255
+ # I'll implement here.
256
+ super
257
+ end
258
+
259
+ def get(param)
260
+ hash = getinfo(false)
261
+ if hash
262
+ return hash[param]
263
+ else
264
+ return :absent
265
+ end
266
+ end
267
+
268
+ def modifycmd(property, value)
269
+ # JJM: This method will assemble a exec vector which modifies
270
+ # a single property and it's value using dscl.
271
+ # JJM: With /usr/bin/dscl, the -create option will destroy an
272
+ # existing property record if it exists
273
+ exec_arg_vector = self.class.get_exec_preamble("-create", @resource[:name])
274
+ # JJM: The following line just maps the NS name to the DS name
275
+ # e.g. { :uid => 'UniqueID' }
276
+ exec_arg_vector << @@ns_to_ds_attribute_map[symbolize(property)]
277
+ # JJM: The following line sends the actual value to set the property to
278
+ exec_arg_vector << value.to_s
279
+ return exec_arg_vector
280
+ end
281
+
282
+ def addcmd
283
+ # JJM 2007-07-24:
284
+ # - addcmd returns an array to be executed to create a new object.
285
+ # - This method is probably being called from the
286
+ # ensure= method in nameservice.rb, or here...
287
+ # - This should only be called if the object doesn't exist.
288
+ # JJM: Blame nameservice.rb for the terse method name. =)
289
+ #
290
+ self.class.get_exec_preamble("-create", @resource[:name])
291
+ end
292
+
293
+ def deletecmd
294
+ # JJM: Like addcmd, only called when deleting the object itself
295
+ # Note, this isn't used to delete properties of the object,
296
+ # at least that's how I understand it...
297
+ self.class.get_exec_preamble("-delete", @resource[:name])
298
+ end
299
+
300
+ def getinfo(refresh = false)
301
+ # JJM 2007-07-24:
302
+ # Override the getinfo method, which is also defined in nameservice.rb
303
+ # This method returns and sets @infohash, which looks like:
304
+ # (NetInfo provider, user type...)
305
+ # @infohash = {:comment=>"Jeff McCune", :home=>"/Users/mccune",
306
+ # :shell=>"/bin/zsh", :password=>"********", :uid=>502, :gid=>502,
307
+ # :name=>"mccune"}
308
+ #
309
+ # I'm not re-factoring the name "getinfo" because this method will be
310
+ # most likely called by nameservice.rb, which I didn't write.
311
+ if refresh or (! defined?(@property_value_cache_hash) or ! @property_value_cache_hash)
312
+ # JJM 2007-07-24: OK, there's a bit of magic that's about to
313
+ # happen... Let's see how strong my grip has become... =)
314
+ #
315
+ # self is a provider instance of some Puppet::Type, like
316
+ # Puppet::Type::User::ProviderDirectoryservice for the case of the
317
+ # user type and this provider.
318
+ #
319
+ # self.class looks like "user provider directoryservice", if that
320
+ # helps you ...
321
+ #
322
+ # self.class.resource_type is a reference to the Puppet::Type class,
323
+ # probably Puppet::Type::User or Puppet::Type::Group, etc...
324
+ #
325
+ # self.class.resource_type.validproperties is a class method,
326
+ # returning an Array of the valid properties of that specific
327
+ # Puppet::Type.
328
+ #
329
+ # So... something like [:comment, :home, :password, :shell, :uid,
330
+ # :groups, :ensure, :gid]
331
+ #
332
+ # Ultimately, we add :name to the list, delete :ensure from the
333
+ # list, then report on the remaining list. Pretty whacky, ehh?
334
+ type_properties = [:name] + self.class.resource_type.validproperties
335
+ type_properties.delete(:ensure) if type_properties.include? :ensure
336
+ @property_value_cache_hash = self.class.single_report(@resource[:name], *type_properties)
337
+ end
338
+ return @property_value_cache_hash
339
+ end
340
+ end
341
+ end
@@ -24,7 +24,7 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
24
24
  # now turn each returned line into a package object
25
25
  process.each { |line|
26
26
  if match = regex.match(line)
27
- hash.clear
27
+ hash = {}
28
28
 
29
29
  fields.zip(match.captures) { |field,value|
30
30
  hash[field] = value
@@ -122,4 +122,4 @@ Puppet::Type.type(:package).provide :dpkg, :parent => Puppet::Provider::Package
122
122
  end
123
123
  end
124
124
 
125
- # $Id: dpkg.rb 2708 2007-07-18 23:48:58Z luke $
125
+ # $Id: dpkg.rb 2753 2007-08-07 02:38:45Z luke $
@@ -21,7 +21,6 @@ Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Packa
21
21
 
22
22
  # now turn each returned line into a package object
23
23
  process.each { |line|
24
- hash.clear
25
24
  if match = regex.match(line)
26
25
  fields.zip(match.captures) { |field,value|
27
26
  hash[field] = value
@@ -32,6 +31,7 @@ Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Packa
32
31
  hash[:provider] = self.name
33
32
 
34
33
  packages << new(hash)
34
+ hash = {}
35
35
  else
36
36
  # Print a warning on lines we can't match, but move
37
37
  # on, since it should be non-fatal
@@ -85,4 +85,4 @@ Puppet::Type.type(:package).provide :openbsd, :parent => Puppet::Provider::Packa
85
85
  end
86
86
  end
87
87
 
88
- # $Id: openbsd.rb 2555 2007-06-08 17:20:00Z luke $
88
+ # $Id: openbsd.rb 2753 2007-08-07 02:38:45Z luke $
@@ -30,13 +30,11 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
30
30
  # our regex for matching dpkg output
31
31
  regex = %r{^(\S+)\s+(\S+)}
32
32
  fields = [:name, :ensure]
33
- hash = {}
34
33
 
35
34
  # now turn each returned line into a package object
36
35
  process.each { |line|
37
36
  if match = regex.match(line)
38
- hash.clear
39
-
37
+ hash = {}
40
38
  fields.zip(match.captures) { |field,value|
41
39
  hash[field] = value
42
40
  }
@@ -129,4 +127,4 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
129
127
  end
130
128
  end
131
129
 
132
- # $Id: rpm.rb 2701 2007-07-16 23:43:50Z luke $
130
+ # $Id: rpm.rb 2753 2007-08-07 02:38:45Z luke $
@@ -43,7 +43,7 @@ Puppet::Type.type(:package).provide :sun, :parent => Puppet::Provider::Package d
43
43
  hash[:provider] = :sun
44
44
 
45
45
  packages << new(hash)
46
- hash.clear
46
+ hash = {}
47
47
  when /\s*(\w+):\s+(.+)/:
48
48
  name = $1
49
49
  value = $2
@@ -167,4 +167,4 @@ Puppet::Type.type(:package).provide :sun, :parent => Puppet::Provider::Package d
167
167
  end
168
168
  end
169
169
 
170
- # $Id: sun.rb 2581 2007-06-14 06:21:40Z luke $
170
+ # $Id: sun.rb 2753 2007-08-07 02:38:45Z luke $
@@ -110,7 +110,7 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
110
110
  def self.instances
111
111
  prefetch()
112
112
  @records.find_all { |r| r[:record_type] == self.name }.collect { |r|
113
- new(clean(r))
113
+ new(r)
114
114
  }
115
115
  end
116
116
 
@@ -134,27 +134,16 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
134
134
  if @property_hash[attr] or self.class.valid_attr?(self.class.name, attr)
135
135
  @property_hash[attr] || :absent
136
136
  else
137
- @resource.should(attr)
137
+ if defined? @resource
138
+ @resource.should(attr)
139
+ else
140
+ nil
141
+ end
138
142
  end
139
143
  end
140
144
 
141
145
  define_method(attr.to_s + "=") do |val|
142
- # Mark that this target was modified.
143
- resourcetarget = @resource.should(:target) || self.class.default_target
144
-
145
- # If they're the same, then just mark that one as modified
146
- if @property_hash[:target] and @property_hash[:target] == resourcetarget
147
- self.class.modified(resourcetarget)
148
- else
149
- # Always mark the resourcetarget as modified, and if there's
150
- # and old property_hash target, mark it as modified and replace
151
- # it.
152
- self.class.modified(resourcetarget)
153
- if @property_hash[:target]
154
- self.class.modified(@property_hash[:target])
155
- end
156
- @property_hash[:target] = resourcetarget
157
- end
146
+ mark_target_modified
158
147
  @property_hash[attr] = val
159
148
  end
160
149
  end
@@ -296,14 +285,13 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
296
285
  header + text
297
286
  end
298
287
 
299
-
300
288
  def create
301
289
  @resource.class.validproperties.each do |property|
302
290
  if value = @resource.should(property)
303
291
  @property_hash[property] = value
304
292
  end
305
293
  end
306
- self.class.modified(@property_hash[:target] || self.class.default_target)
294
+ mark_target_modified()
307
295
  return (@resource.class.name.to_s + "_created").intern
308
296
  end
309
297
 
@@ -338,16 +326,15 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
338
326
  #@property_hash = {}
339
327
  end
340
328
 
341
- def initialize(resource)
329
+ def initialize(record)
342
330
  super
343
331
 
344
- # See if there's already a matching property_hash in the records list;
345
- # else, use a default value.
346
- # We provide a default for 'ensure' here, because the provider will
347
- # override it if the thing exists, but it won't touch it if it doesn't
348
- # exist.
349
- @property_hash = self.class.record?(resource[:name]) ||
350
- {:record_type => self.class.name, :ensure => :absent}
332
+ # The 'record' could be a resource or a record, depending on how the provider
333
+ # is initialized. If we got an empty property hash (probably because the resource
334
+ # is just being initialized), then we want to set up some defualts.
335
+ if @property_hash.empty?
336
+ @property_hash = self.class.record?(resource[:name]) || {:record_type => self.class.name, :ensure => :absent}
337
+ end
351
338
  end
352
339
 
353
340
  # Retrieve the current state from disk.
@@ -357,6 +344,22 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
357
344
  end
358
345
  self.class.prefetch(@resource[:name] => @resource)
359
346
  end
347
+
348
+ def record_type
349
+ @property_hash[:record_type]
350
+ end
351
+
352
+ private
353
+
354
+ # Mark both the resource and provider target as modified.
355
+ def mark_target_modified
356
+ if defined? @resource and restarget = @resource.should(:target) and restarget != @property_hash[:target]
357
+ self.class.modified(restarget)
358
+ end
359
+ if @property_hash[:target] != :absent
360
+ self.class.modified(@property_hash[:target])
361
+ end
362
+ end
360
363
  end
361
364
 
362
- # $Id: parsedfile.rb 2722 2007-07-20 16:27:44Z luke $
365
+ # $Id: parsedfile.rb 2750 2007-08-06 17:59:37Z luke $