puppet 2.6.8 → 2.6.9

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 (60) hide show
  1. data/CHANGELOG +41 -0
  2. data/{README.rst → README.md} +17 -10
  3. data/conf/redhat/puppet.spec +93 -22
  4. data/ext/vim/README +2 -1
  5. data/ext/vim/ftplugin/puppet.vim +94 -0
  6. data/ext/vim/indent/puppet.vim +76 -0
  7. data/lib/puppet.rb +2 -3
  8. data/lib/puppet/application/agent.rb +3 -3
  9. data/lib/puppet/application/apply.rb +16 -5
  10. data/lib/puppet/configurer.rb +60 -56
  11. data/lib/puppet/configurer/fact_handler.rb +6 -1
  12. data/lib/puppet/defaults.rb +19 -0
  13. data/lib/puppet/file_serving/fileset.rb +1 -1
  14. data/lib/puppet/indirector/exec.rb +3 -3
  15. data/lib/puppet/indirector/queue.rb +1 -1
  16. data/lib/puppet/metatype/manager.rb +7 -20
  17. data/lib/puppet/parser/compiler.rb +17 -16
  18. data/lib/puppet/parser/resource.rb +18 -1
  19. data/lib/puppet/parser/scope.rb +2 -2
  20. data/lib/puppet/provider/mount/parsed.rb +1 -1
  21. data/lib/puppet/provider/naginator.rb +9 -1
  22. data/lib/puppet/provider/nameservice/directoryservice.rb +11 -8
  23. data/lib/puppet/provider/package/aptitude.rb +1 -0
  24. data/lib/puppet/rails/host.rb +7 -0
  25. data/lib/puppet/resource/catalog.rb +9 -3
  26. data/lib/puppet/transaction.rb +15 -26
  27. data/lib/puppet/transaction/report.rb +3 -3
  28. data/lib/puppet/type.rb +13 -24
  29. data/lib/puppet/util/queue.rb +1 -1
  30. data/lib/puppet/util/queue/stomp.rb +2 -2
  31. data/lib/puppet/util/settings/file_setting.rb +1 -0
  32. data/spec/integration/defaults_spec.rb +22 -0
  33. data/spec/integration/indirector/catalog/queue_spec.rb +2 -2
  34. data/spec/integration/type_spec.rb +11 -0
  35. data/spec/unit/application/agent_spec.rb +2 -2
  36. data/spec/unit/application/apply_spec.rb +62 -50
  37. data/spec/unit/configurer/fact_handler_spec.rb +43 -37
  38. data/spec/unit/configurer_spec.rb +404 -327
  39. data/spec/unit/file_serving/fileset_spec.rb +7 -0
  40. data/spec/unit/indirector/exec_spec.rb +4 -4
  41. data/spec/unit/indirector/node/exec_spec.rb +1 -1
  42. data/spec/unit/indirector/queue_spec.rb +4 -4
  43. data/spec/unit/node_spec.rb +1 -0
  44. data/spec/unit/parser/compiler_spec.rb +8 -46
  45. data/spec/unit/parser/resource_spec.rb +61 -3
  46. data/spec/unit/parser/scope_spec.rb +9 -3
  47. data/spec/unit/provider/nameservice/directoryservice_spec.rb +60 -0
  48. data/spec/unit/rails/host_spec.rb +8 -0
  49. data/spec/unit/resource/catalog_spec.rb +1 -1
  50. data/spec/unit/transaction/report_spec.rb +3 -3
  51. data/spec/unit/transaction_spec.rb +8 -2
  52. data/spec/unit/type_spec.rb +66 -0
  53. data/spec/unit/util/queue/stomp_spec.rb +10 -10
  54. data/spec/unit/util/settings/file_setting_spec.rb +4 -0
  55. metadata +1229 -1232
  56. data/README +0 -31
  57. data/lib/puppet/provider/nameservice/#directoryservice.rb# +0 -519
  58. data/lib/puppet/reference/#providers.rb# +0 -123
  59. data/spec/unit/indirector/certificate_status/#file_spec.rb# +0 -188
  60. data/spec/unit/resource/#type_collection_spec.rb# +0 -463
data/README DELETED
@@ -1,31 +0,0 @@
1
- Documentation (and detailed install instructions) can be found
2
- online at http://docs.puppetlabs.com/.
3
-
4
- Additional documentation can also be found at the Puppet Wiki:
5
-
6
- http://projects.puppetlabs.com/projects/puppet/wiki/
7
-
8
- Generally, you need the following things installed:
9
-
10
- * Ruby >= 1.8.1 (earlier releases might work but probably not)
11
-
12
- * The Ruby OpenSSL library. For some reason, this often isn't included
13
- in the main ruby distributions. You can test for it by running
14
- 'ruby -ropenssl -e "puts :yep"'. If that errors out, you're missing the
15
- library.
16
-
17
- If your distribution doesn't come with the necessary library (e.g., on Debian
18
- and Ubuntu you need to install libopenssl-ruby), then you'll probably have to
19
- compile Ruby yourself, since it's part of the standard library and not
20
- available separately. You could probably just compile and install that one
21
- library, though.
22
-
23
- * The Ruby XMLRPC client and server libraries. For some reason, this often
24
- isn't included in the main ruby distributions. You can test for it by
25
- running 'ruby -rxmlrpc/client -e "puts :yep"'. If that errors out, you're missing
26
- the library.
27
-
28
- * Facter => 1.5.1
29
- You can get this from < http://puppetlabs.com/projects/facter >
30
-
31
- $Id$
@@ -1,519 +0,0 @@
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
- require 'facter/util/plist'
18
- require 'cgi'
19
-
20
-
21
- class Puppet::Provider::NameService
22
- class DirectoryService < Puppet::Provider::NameService
23
- # JJM: Dive into the singleton_class
24
- class << self
25
- # JJM: This allows us to pass information when calling
26
- # Puppet::Type.type
27
- # e.g. Puppet::Type.type(:user).provide :directoryservice, :ds_path => "Users"
28
- # This is referenced in the get_ds_path class method
29
- attr_writer :ds_path
30
- attr_writer :macosx_version_major
31
- end
32
-
33
- initvars
34
-
35
- commands :dscl => "/usr/bin/dscl"
36
- commands :dseditgroup => "/usr/sbin/dseditgroup"
37
- commands :sw_vers => "/usr/bin/sw_vers"
38
- confine :operatingsystem => :darwin
39
- defaultfor :operatingsystem => :darwin
40
-
41
-
42
- # JJM 2007-07-25: This map is used to map NameService attributes to their
43
- # corresponding DirectoryService attribute names.
44
- # See: http://images.apple.com/server/docs.Open_Directory_v10.4.pdf
45
- # JJM: Note, this is de-coupled from the Puppet::Type, and must
46
- # be actively maintained. There may also be collisions with different
47
- # types (Users, Groups, Mounts, Hosts, etc...)
48
- @@ds_to_ns_attribute_map = {
49
- 'RecordName' => :name,
50
- 'PrimaryGroupID' => :gid,
51
- 'NFSHomeDirectory' => :home,
52
- 'UserShell' => :shell,
53
- 'UniqueID' => :uid,
54
- 'RealName' => :comment,
55
- 'Password' => :password,
56
- 'GeneratedUID' => :guid,
57
- 'IPAddress' => :ip_address,
58
- 'ENetAddress' => :en_address,
59
- 'GroupMembership' => :members,
60
- }
61
- # JJM The same table as above, inverted.
62
- @@ns_to_ds_attribute_map = {
63
- :name => 'RecordName',
64
- :gid => 'PrimaryGroupID',
65
- :home => 'NFSHomeDirectory',
66
- :shell => 'UserShell',
67
- :uid => 'UniqueID',
68
- :comment => 'RealName',
69
- :password => 'Password',
70
- :guid => 'GeneratedUID',
71
- :en_address => 'ENetAddress',
72
- :ip_address => 'IPAddress',
73
- :members => 'GroupMembership',
74
- }
75
-
76
- @@password_hash_dir = "/var/db/shadow/hash"
77
-
78
- def self.instances
79
- # JJM Class method that provides an array of instance objects of this
80
- # type.
81
- # JJM: Properties are dependent on the Puppet::Type we're managine.
82
- type_property_array = [:name] + @resource_type.validproperties
83
-
84
- # Create a new instance of this Puppet::Type for each object present
85
- # on the system.
86
- list_all_present.collect do |name_string|
87
- self.new(single_report(name_string, *type_property_array))
88
- end
89
- end
90
-
91
- def self.get_ds_path
92
- # JJM: 2007-07-24 This method dynamically returns the DS path we're concerned with.
93
- # For example, if we're working with an user type, this will be /Users
94
- # with a group type, this will be /Groups.
95
- # @ds_path is an attribute of the class itself.
96
- return @ds_path if defined?(@ds_path)
97
- # JJM: "Users" or "Groups" etc ... (Based on the Puppet::Type)
98
- # Remember this is a class method, so self.class is Class
99
- # Also, @resource_type seems to be the reference to the
100
- # Puppet::Type this class object is providing for.
101
- @resource_type.name.to_s.capitalize + "s"
102
- end
103
-
104
- def self.get_macosx_version_major
105
- return @macosx_version_major if defined?(@macosx_version_major)
106
- begin
107
- # Make sure we've loaded all of the facts
108
- Facter.loadfacts
109
-
110
- if Facter.value(:macosx_productversion_major)
111
- product_version_major = Facter.value(:macosx_productversion_major)
112
- else
113
- # TODO: remove this code chunk once we require Facter 1.5.5 or higher.
114
- Puppet.warning("DEPRECATION WARNING: Future versions of the directoryservice provider will require Facter 1.5.5 or newer.")
115
- product_version = Facter.value(:macosx_productversion)
116
- fail("Could not determine OS X version from Facter") if product_version.nil?
117
- product_version_major = product_version.scan(/(\d+)\.(\d+)./).join(".")
118
- end
119
- fail("#{product_version_major} is not supported by the directoryservice provider") if %w{10.0 10.1 10.2 10.3}.include?(product_version_major)
120
- @macosx_version_major = product_version_major
121
- return @macosx_version_major
122
- rescue Puppet::ExecutionFailure => detail
123
- fail("Could not determine OS X version: #{detail}")
124
- end
125
- end
126
-
127
-
128
- def self.list_all_present
129
- # JJM: List all objects of this Puppet::Type already present on the system.
130
- begin
131
- dscl_output = execute(get_exec_preamble("-list"))
132
- rescue Puppet::ExecutionFailure => detail
133
- fail("Could not get #{@resource_type.name} list from DirectoryService")
134
- end
135
- dscl_output.split("\n")
136
- end
137
-
138
- def self.parse_dscl_url_data(dscl_output)
139
- # we need to construct a Hash from the dscl -url output to match
140
- # that returned by the dscl -plist output for 10.5+ clients.
141
- #
142
- # Nasty assumptions:
143
- # a) no values *end* in a colon ':', only keys
144
- # b) if a line ends in a colon and the next line does start with
145
- # a space, then the second line is a value of the first.
146
- # c) (implied by (b)) keys don't start with spaces.
147
-
148
- dscl_plist = {}
149
- dscl_output.split("\n").inject([]) do |array, line|
150
- if line =~ /^\s+/ # it's a value
151
- array[-1] << line # add the value to the previous key
152
- else
153
- array << line
154
- end
155
- array
156
- end.compact
157
-
158
- dscl_output.each do |line|
159
- # This should be a 'normal' entry. key and value on one line.
160
- # We split on ': ' to deal with keys/values with a colon in them.
161
- split_array = line.split(/:\s+/)
162
- key = split_array.first
163
- value = CGI::unescape(split_array.last.strip.chomp)
164
- # We need to treat GroupMembership separately as it is currently
165
- # the only attribute we care about multiple values for, and
166
- # the values can never contain spaces (shortnames)
167
- # We also make every value an array to be consistent with the
168
- # output of dscl -plist under 10.5
169
- if key == "GroupMembership"
170
- dscl_plist[key] = value.split(/\s/)
171
- else
172
- dscl_plist[key] = [value]
173
- end
174
- end
175
- dscl_plist
176
- end
177
-
178
- def self.parse_dscl_plist_data(dscl_output)
179
- Plist.parse_xml(dscl_output)
180
- end
181
-
182
- def self.generate_attribute_hash(input_hash, *type_properties)
183
- attribute_hash = {}
184
- input_hash.keys.each do |key|
185
- ds_attribute = key.sub("dsAttrTypeStandard:", "")
186
- next unless (@@ds_to_ns_attribute_map.keys.include?(ds_attribute) and type_properties.include? @@ds_to_ns_attribute_map[ds_attribute])
187
- ds_value = input_hash[key]
188
- case @@ds_to_ns_attribute_map[ds_attribute]
189
- when :members
190
- ds_value = ds_value # only members uses arrays so far
191
- when :gid, :uid
192
- # OS X stores objects like uid/gid as strings.
193
- # Try casting to an integer for these cases to be
194
- # consistent with the other providers and the group type
195
- # validation
196
- begin
197
- ds_value = Integer(ds_value[0])
198
- rescue ArgumentError
199
- ds_value = ds_value[0]
200
- end
201
- else ds_value = ds_value[0]
202
- end
203
- attribute_hash[@@ds_to_ns_attribute_map[ds_attribute]] = ds_value
204
- end
205
-
206
- # NBK: need to read the existing password here as it's not actually
207
- # stored in the user record. It is stored at a path that involves the
208
- # UUID of the user record for non-Mobile local acccounts.
209
- # Mobile Accounts are out of scope for this provider for now
210
- attribute_hash[:password] = self.get_password(attribute_hash[:guid]) if @resource_type.validproperties.include?(:password) and Puppet.features.root?
211
- attribute_hash
212
- end
213
-
214
- def self.single_report(resource_name, *type_properties)
215
- # JJM 2007-07-24:
216
- # Given a the name of an object and a list of properties of that
217
- # object, return all property values in a hash.
218
- #
219
- # This class method returns nil if the object doesn't exist
220
- # Otherwise, it returns a hash of the object properties.
221
-
222
- all_present_str_array = list_all_present
223
-
224
- # NBK: shortcut the process if the resource is missing
225
- return nil unless all_present_str_array.include? resource_name
226
-
227
- dscl_vector = get_exec_preamble("-read", resource_name)
228
- begin
229
- dscl_output = execute(dscl_vector)
230
- rescue Puppet::ExecutionFailure => detail
231
- fail("Could not get report. command execution failed.")
232
- end
233
-
234
- # Two code paths is ugly, but until we can drop 10.4 support we don't
235
- # have a lot of choice. Ultimately this should all be done using Ruby
236
- # to access the DirectoryService APIs directly, but that's simply not
237
- # feasible for a while yet.
238
- if self.get_macosx_version_major > "10.4"
239
- dscl_plist = self.parse_dscl_plist_data(dscl_output)
240
- elsif self.get_macosx_version_major == "10.4"
241
- dscl_plist = self.parse_dscl_url_data(dscl_output)
242
- else
243
- fail("Puppet does not support OS X versions < 10.4")
244
- end
245
-
246
- self.generate_attribute_hash(dscl_plist, *type_properties)
247
- end
248
-
249
- def self.get_exec_preamble(ds_action, resource_name = nil)
250
- # JJM 2007-07-24
251
- # DSCL commands are often repetitive and contain the same positional
252
- # arguments over and over. See http://developer.apple.com/documentation/Porting/Conceptual/PortingUnix/additionalfeatures/chapter_10_section_9.html
253
- # for an example of what I mean.
254
- # This method spits out proper DSCL commands for us.
255
- # We EXPECT name to be @resource[:name] when called from an instance object.
256
-
257
- # 10.4 doesn't support the -plist option for dscl, and 10.5 has a
258
- # different format for the -url output with objects with spaces in
259
- # their values. *sigh*. Use -url for 10.4 in the hope this can be
260
- # deprecated one day, and use -plist for 10.5 and higher.
261
- if self.get_macosx_version_major > "10.4"
262
- command_vector = [ command(:dscl), "-plist", "." ]
263
- elsif self.get_macosx_version_major == "10.4"
264
- command_vector = [ command(:dscl), "-url", "." ]
265
- else
266
- fail("Puppet does not support OS X versions < 10.4")
267
- end
268
-
269
- # JJM: The actual action to perform. See "man dscl"
270
- # Common actiosn: -create, -delete, -merge, -append, -passwd
271
- command_vector << ds_action
272
- # JJM: get_ds_path will spit back "Users" or "Groups",
273
- # etc... Depending on the Puppet::Type of our self.
274
- if resource_name
275
- command_vector << "/#{get_ds_path}/#{resource_name}"
276
- else
277
- command_vector << "/#{get_ds_path}"
278
- end
279
- # JJM: This returns most of the preamble of the command.
280
- # e.g. 'dscl / -create /Users/mccune'
281
- command_vector
282
- end
283
-
284
- def self.set_password(resource_name, guid, password_hash)
285
- password_hash_file = "#{@@password_hash_dir}/#{guid}"
286
- begin
287
- File.open(password_hash_file, 'w') { |f| f.write(password_hash)}
288
- rescue Errno::EACCES => detail
289
- fail("Could not write to password hash file: #{detail}")
290
- end
291
-
292
- # NBK: For shadow hashes, the user AuthenticationAuthority must contain a value of
293
- # ";ShadowHash;". The LKDC in 10.5 makes this more interesting though as it
294
- # will dynamically generate ;Kerberosv5;;username@LKDC:SHA1 attributes if
295
- # missing. Thus we make sure we only set ;ShadowHash; if it is missing, and
296
- # we can do this with the merge command. This allows people to continue to
297
- # use other custom AuthenticationAuthority attributes without stomping on them.
298
- #
299
- # There is a potential problem here in that we're only doing this when setting
300
- # the password, and the attribute could get modified at other times while the
301
- # hash doesn't change and so this doesn't get called at all... but
302
- # without switching all the other attributes to merge instead of create I can't
303
- # see a simple enough solution for this that doesn't modify the user record
304
- # every single time. This should be a rather rare edge case. (famous last words)
305
-
306
- dscl_vector = self.get_exec_preamble("-merge", resource_name)
307
- dscl_vector << "AuthenticationAuthority" << ";ShadowHash;"
308
- begin
309
- dscl_output = execute(dscl_vector)
310
- rescue Puppet::ExecutionFailure => detail
311
- fail("Could not set AuthenticationAuthority.")
312
- end
313
- end
314
-
315
- def self.get_password(guid)
316
- password_hash = nil
317
- password_hash_file = "#{@@password_hash_dir}/#{guid}"
318
- if File.exists?(password_hash_file) and File.file?(password_hash_file)
319
- fail("Could not read password hash file at #{password_hash_file}") if not File.readable?(password_hash_file)
320
- f = File.new(password_hash_file)
321
- password_hash = f.read
322
- f.close
323
- end
324
- password_hash
325
- end
326
-
327
- def ensure=(ensure_value)
328
- super
329
- # We need to loop over all valid properties for the type we're
330
- # managing and call the method which sets that property value
331
- # dscl can't create everything at once unfortunately.
332
- if ensure_value == :present
333
- @resource.class.validproperties.each do |name|
334
- next if name == :ensure
335
- # LAK: We use property.sync here rather than directly calling
336
- # the settor method because the properties might do some kind
337
- # of conversion. In particular, the user gid property might
338
- # have a string and need to convert it to a number
339
- if @resource.should(name)
340
- @resource.property(name).sync
341
- elsif value = autogen(name)
342
- self.send(name.to_s + "=", value)
343
- else
344
- next
345
- end
346
- end
347
- end
348
- end
349
-
350
- def password=(passphrase)
351
- exec_arg_vector = self.class.get_exec_preamble("-read", @resource.name)
352
- exec_arg_vector << @@ns_to_ds_attribute_map[:guid]
353
- begin
354
- guid_output = execute(exec_arg_vector)
355
- guid_plist = Plist.parse_xml(guid_output)
356
- # Although GeneratedUID like all DirectoryService values can be multi-valued
357
- # according to the schema, in practice user accounts cannot have multiple UUIDs
358
- # otherwise Bad Things Happen, so we just deal with the first value.
359
- guid = guid_plist["dsAttrTypeStandard:#{@@ns_to_ds_attribute_map[:guid]}"][0]
360
- self.class.set_password(@resource.name, guid, passphrase)
361
- rescue Puppet::ExecutionFailure => detail
362
- fail("Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}")
363
- end
364
- end
365
-
366
- # NBK: we override @parent.set as we need to execute a series of commands
367
- # to deal with array values, rather than the single command nameservice.rb
368
- # expects to be returned by modifycmd. Thus we don't bother defining modifycmd.
369
-
370
- def set(param, value)
371
- self.class.validate(param, value)
372
- current_members = @property_value_cache_hash[:members]
373
- if param == :members
374
- # If we are meant to be authoritative for the group membership
375
- # then remove all existing members who haven't been specified
376
- # in the manifest.
377
- remove_unwanted_members(current_members, value) if @resource[:auth_membership] and not current_members.nil?
378
-
379
- # if they're not a member, make them one.
380
- add_members(current_members, value)
381
- else
382
- exec_arg_vector = self.class.get_exec_preamble("-create", @resource[:name])
383
- # JJM: The following line just maps the NS name to the DS name
384
- # e.g. { :uid => 'UniqueID' }
385
- exec_arg_vector << @@ns_to_ds_attribute_map[symbolize(param)]
386
- # JJM: The following line sends the actual value to set the property to
387
- exec_arg_vector << value.to_s
388
- begin
389
- execute(exec_arg_vector)
390
- rescue Puppet::ExecutionFailure => detail
391
- fail("Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}")
392
- end
393
- end
394
- end
395
-
396
- # NBK: we override @parent.create as we need to execute a series of commands
397
- # to create objects with dscl, rather than the single command nameservice.rb
398
- # expects to be returned by addcmd. Thus we don't bother defining addcmd.
399
- def create
400
- if exists?
401
- info "already exists"
402
- return nil
403
- end
404
-
405
- # NBK: First we create the object with a known guid so we can set the contents
406
- # of the password hash if required
407
- # Shelling out sucks, but for a single use case it doesn't seem worth
408
- # requiring people install a UUID library that doesn't come with the system.
409
- # This should be revisited if Puppet starts managing UUIDs for other platform
410
- # user records.
411
- guid = %x{/usr/bin/uuidgen}.chomp
412
-
413
- exec_arg_vector = self.class.get_exec_preamble("-create", @resource[:name])
414
- exec_arg_vector << @@ns_to_ds_attribute_map[:guid] << guid
415
- begin
416
- execute(exec_arg_vector)
417
- rescue Puppet::ExecutionFailure => detail
418
- fail("Could not set GeneratedUID for #{@resource.class.name} #{@resource.name}: #{detail}")
419
- end
420
-
421
- if value = @resource.should(:password) and value != ""
422
- self.class.set_password(@resource[:name], guid, value)
423
- end
424
-
425
- # Now we create all the standard properties
426
- Puppet::Type.type(@resource.class.name).validproperties.each do |property|
427
- next if property == :ensure
428
- if value = @resource.should(property) and value != ""
429
- if property == :members
430
- add_members(nil, value)
431
- else
432
- exec_arg_vector = self.class.get_exec_preamble("-create", @resource[:name])
433
- exec_arg_vector << @@ns_to_ds_attribute_map[symbolize(property)]
434
- next if property == :password # skip setting the password here
435
- exec_arg_vector << value.to_s
436
- begin
437
- execute(exec_arg_vector)
438
- rescue Puppet::ExecutionFailure => detail
439
- fail("Could not create #{@resource.class.name} #{@resource.name}: #{detail}")
440
- end
441
- end
442
- end
443
- end
444
- end
445
-
446
- def remove_unwanted_members(current_members, new_members)
447
- current_members.each do |member|
448
- if not new_members.flatten.include?(member)
449
- cmd = [:dseditgroup, "-o", "edit", "-n", ".", "-d", member, @resource[:name]]
450
- begin
451
- execute(cmd)
452
- rescue Puppet::ExecutionFailure => detail
453
- fail("Could not remove #{member} from group: #{@resource.name}, #{detail}")
454
- end
455
- end
456
- end
457
- end
458
-
459
- def add_members(current_members, new_members)
460
- new_members.flatten.each do |new_member|
461
- if current_members.nil? or not current_members.include?(new_member)
462
- cmd = [:dseditgroup, "-o", "edit", "-n", ".", "-a", new_member, @resource[:name]]
463
- begin
464
- execute(cmd)
465
- rescue Puppet::ExecutionFailure => detail
466
- fail("Could not add #{new_member} to group: #{@resource.name}, #{detail}")
467
- end
468
- end
469
- end
470
- end
471
-
472
- def deletecmd
473
- # JJM: Like addcmd, only called when deleting the object itself
474
- # Note, this isn't used to delete properties of the object,
475
- # at least that's how I understand it...
476
- self.class.get_exec_preamble("-delete", @resource[:name])
477
- end
478
-
479
- def getinfo(refresh = false)
480
- # JJM 2007-07-24:
481
- # Override the getinfo method, which is also defined in nameservice.rb
482
- # This method returns and sets @infohash
483
- # I'm not re-factoring the name "getinfo" because this method will be
484
- # most likely called by nameservice.rb, which I didn't write.
485
- if refresh or (! defined?(@property_value_cache_hash) or ! @property_value_cache_hash)
486
- # JJM 2007-07-24: OK, there's a bit of magic that's about to
487
- # happen... Let's see how strong my grip has become... =)
488
- #
489
- # self is a provider instance of some Puppet::Type, like
490
- # Puppet::Type::User::ProviderDirectoryservice for the case of the
491
- # user type and this provider.
492
- #
493
- # self.class looks like "user provider directoryservice", if that
494
- # helps you ...
495
- #
496
- # self.class.resource_type is a reference to the Puppet::Type class,
497
- # probably Puppet::Type::User or Puppet::Type::Group, etc...
498
- #
499
- # self.class.resource_type.validproperties is a class method,
500
- # returning an Array of the valid properties of that specific
501
- # Puppet::Type.
502
- #
503
- # So... something like [:comment, :home, :password, :shell, :uid,
504
- # :groups, :ensure, :gid]
505
- #
506
- # Ultimately, we add :name to the list, delete :ensure from the
507
- # list, then report on the remaining list. Pretty whacky, ehh?
508
- type_properties = [:name] + self.class.resource_type.validproperties
509
- type_properties.delete(:ensure) if type_properties.include? :ensure
510
- type_properties << :guid # append GeneratedUID so we just get the report here
511
- @property_value_cache_hash = self.class.single_report(@resource[:name], *type_properties)
512
- [:uid, :gid].each do |param|
513
- @property_value_cache_hash[param] = @property_value_cache_hash[param].to_i if @property_value_cache_hash and @property_value_cache_hash.include?(param)
514
- end
515
- end
516
- @property_value_cache_hash
517
- end
518
- end
519
- end