puppet 0.13.6 → 0.16.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 (149) hide show
  1. data/CHANGELOG +57 -0
  2. data/Rakefile +38 -410
  3. data/bin/puppet +14 -12
  4. data/bin/puppetca +1 -3
  5. data/bin/puppetd +25 -7
  6. data/bin/puppetdoc +161 -104
  7. data/bin/puppetmasterd +4 -4
  8. data/conf/epm.list +8 -0
  9. data/conf/redhat/client.init +6 -1
  10. data/conf/redhat/no-chuser-0.15.1.patch +38 -0
  11. data/conf/redhat/puppet.spec +20 -5
  12. data/conf/redhat/puppetd.conf +1 -1
  13. data/conf/redhat/puppetmasterd.conf +1 -1
  14. data/conf/redhat/server.init +2 -4
  15. data/examples/code/snippets/{casestatement → casestatement.pp} +12 -1
  16. data/examples/code/snippets/selectorvalues.pp +15 -0
  17. data/examples/code/snippets/singleselector.pp +22 -0
  18. data/examples/code/snippets/tag.pp +9 -0
  19. data/ext/module_puppet +1 -1
  20. data/install.rb +303 -303
  21. data/lib/puppet.rb +7 -9
  22. data/lib/puppet/client.rb +18 -5
  23. data/lib/puppet/client/dipper.rb +12 -10
  24. data/lib/puppet/client/master.rb +113 -41
  25. data/lib/puppet/client/pelement.rb +20 -0
  26. data/lib/puppet/config.rb +113 -6
  27. data/lib/puppet/element.rb +1 -3
  28. data/lib/puppet/event.rb +12 -23
  29. data/lib/puppet/filetype.rb +93 -5
  30. data/lib/puppet/inifile.rb +201 -0
  31. data/lib/puppet/log.rb +18 -6
  32. data/lib/puppet/parameter.rb +80 -29
  33. data/lib/puppet/parser/ast.rb +6 -4
  34. data/lib/puppet/parser/ast/caseopt.rb +13 -4
  35. data/lib/puppet/parser/ast/casestatement.rb +2 -2
  36. data/lib/puppet/parser/ast/component.rb +4 -14
  37. data/lib/puppet/parser/ast/hostclass.rb +1 -1
  38. data/lib/puppet/parser/ast/leaf.rb +12 -0
  39. data/lib/puppet/parser/ast/node.rb +4 -4
  40. data/lib/puppet/parser/ast/objectdef.rb +5 -51
  41. data/lib/puppet/parser/ast/selector.rb +2 -0
  42. data/lib/puppet/parser/ast/tag.rb +26 -0
  43. data/lib/puppet/parser/interpreter.rb +89 -74
  44. data/lib/puppet/parser/lexer.rb +4 -3
  45. data/lib/puppet/parser/parser.rb +440 -378
  46. data/lib/puppet/parser/scope.rb +844 -887
  47. data/lib/puppet/server.rb +12 -1
  48. data/lib/puppet/server/authconfig.rb +166 -0
  49. data/lib/puppet/server/authstore.rb +8 -6
  50. data/lib/puppet/server/ca.rb +23 -26
  51. data/lib/puppet/server/filebucket.rb +24 -23
  52. data/lib/puppet/server/fileserver.rb +116 -47
  53. data/lib/puppet/server/master.rb +58 -19
  54. data/lib/puppet/server/pelement.rb +176 -0
  55. data/lib/puppet/server/rights.rb +78 -0
  56. data/lib/puppet/server/servlet.rb +19 -6
  57. data/lib/puppet/sslcertificates.rb +4 -2
  58. data/lib/puppet/sslcertificates/ca.rb +66 -34
  59. data/lib/puppet/storage.rb +20 -26
  60. data/lib/puppet/transaction.rb +49 -92
  61. data/lib/puppet/type.rb +142 -35
  62. data/lib/puppet/type/cron.rb +29 -14
  63. data/lib/puppet/type/exec.rb +92 -35
  64. data/lib/puppet/type/group.rb +29 -11
  65. data/lib/puppet/type/nameservice.rb +50 -1
  66. data/lib/puppet/type/nameservice/netinfo.rb +68 -1
  67. data/lib/puppet/type/nameservice/objectadd.rb +1 -0
  68. data/lib/puppet/type/package.rb +150 -109
  69. data/lib/puppet/type/package/apple.rb +27 -0
  70. data/lib/puppet/type/package/apt.rb +1 -0
  71. data/lib/puppet/type/package/darwinport.rb +97 -0
  72. data/lib/puppet/type/package/dpkg.rb +10 -2
  73. data/lib/puppet/type/package/freebsd.rb +19 -0
  74. data/lib/puppet/type/package/{bsd.rb → openbsd.rb} +36 -7
  75. data/lib/puppet/type/package/ports.rb +98 -0
  76. data/lib/puppet/type/package/rpm.rb +43 -7
  77. data/lib/puppet/type/package/sun.rb +53 -36
  78. data/lib/puppet/type/package/yum.rb +5 -16
  79. data/lib/puppet/type/parsedtype.rb +41 -29
  80. data/lib/puppet/type/parsedtype/host.rb +13 -5
  81. data/lib/puppet/type/parsedtype/mount.rb +250 -0
  82. data/lib/puppet/type/parsedtype/port.rb +8 -6
  83. data/lib/puppet/type/pfile.rb +284 -30
  84. data/lib/puppet/type/pfile/checksum.rb +96 -68
  85. data/lib/puppet/type/pfile/content.rb +16 -13
  86. data/lib/puppet/type/pfile/ensure.rb +64 -126
  87. data/lib/puppet/type/pfile/group.rb +12 -5
  88. data/lib/puppet/type/pfile/mode.rb +16 -4
  89. data/lib/puppet/type/pfile/source.rb +47 -73
  90. data/lib/puppet/type/pfile/target.rb +81 -0
  91. data/lib/puppet/type/pfile/uid.rb +10 -3
  92. data/lib/puppet/type/pfilebucket.rb +12 -3
  93. data/lib/puppet/type/schedule.rb +5 -1
  94. data/lib/puppet/type/service.rb +138 -66
  95. data/lib/puppet/type/service/debian.rb +9 -3
  96. data/lib/puppet/type/service/init.rb +51 -56
  97. data/lib/puppet/type/service/smf.rb +16 -6
  98. data/lib/puppet/type/state.rb +71 -32
  99. data/lib/puppet/type/symlink.rb +12 -7
  100. data/lib/puppet/type/tidy.rb +5 -1
  101. data/lib/puppet/type/user.rb +116 -20
  102. data/lib/puppet/type/yumrepo.rb +314 -0
  103. data/lib/puppet/util.rb +84 -14
  104. data/test/client/client.rb +41 -18
  105. data/test/client/master.rb +50 -4
  106. data/test/executables/puppetbin.rb +31 -4
  107. data/test/executables/puppetca.rb +18 -2
  108. data/test/language/ast.rb +201 -31
  109. data/test/language/interpreter.rb +8 -2
  110. data/test/{parser → language}/lexer.rb +1 -1
  111. data/test/language/node.rb +84 -0
  112. data/test/{parser → language}/parser.rb +1 -1
  113. data/test/language/scope.rb +101 -2
  114. data/test/language/snippets.rb +23 -2
  115. data/test/other/config.rb +99 -1
  116. data/test/other/filetype.rb +95 -0
  117. data/test/other/inifile.rb +114 -0
  118. data/test/other/log.rb +3 -2
  119. data/test/other/transactions.rb +55 -10
  120. data/test/puppet/utiltest.rb +25 -1
  121. data/test/puppettest.rb +140 -46
  122. data/test/server/authconfig.rb +56 -0
  123. data/test/server/bucket.rb +32 -18
  124. data/test/server/fileserver.rb +75 -30
  125. data/test/server/master.rb +27 -4
  126. data/test/server/pelement.rb +298 -0
  127. data/test/server/rights.rb +41 -0
  128. data/test/server/server.rb +2 -2
  129. data/test/tagging/tagging.rb +100 -1
  130. data/test/types/basic.rb +3 -3
  131. data/test/types/cron.rb +24 -1
  132. data/test/types/exec.rb +99 -1
  133. data/test/types/file.rb +298 -2
  134. data/test/types/filebucket.rb +4 -15
  135. data/test/types/filesources.rb +43 -14
  136. data/test/types/group.rb +1 -13
  137. data/test/types/mount.rb +277 -0
  138. data/test/types/package.rb +164 -33
  139. data/test/types/parameter.rb +107 -0
  140. data/test/types/port.rb +2 -1
  141. data/test/types/service.rb +37 -2
  142. data/test/types/state.rb +92 -0
  143. data/test/types/symlink.rb +30 -2
  144. data/test/types/tidy.rb +2 -14
  145. data/test/types/type.rb +35 -1
  146. data/test/types/user.rb +110 -1
  147. data/test/types/yumrepo.rb +95 -0
  148. metadata +316 -290
  149. data/test/types/filetype.rb +0 -160
@@ -5,7 +5,9 @@ require 'puppet/type/service/init'
5
5
  Puppet.type(:service).newsvctype(:debian, :init) do
6
6
  # Remove the symlinks
7
7
  def disable
8
- output = %x{update-rc.d -f #{self[:name]} remove 2>&1}
8
+ cmd = %{update-rc.d -f #{self[:name]} remove 2>&1}
9
+ self.debug "Executing '%s'" % cmd
10
+ output = %x{#{cmd}}
9
11
 
10
12
  unless $? == 0
11
13
  raise Puppet::Error, "Could not disable %s: %s" %
@@ -14,7 +16,9 @@ Puppet.type(:service).newsvctype(:debian, :init) do
14
16
  end
15
17
 
16
18
  def enabled?
17
- output = %x{update-rc.d -n -f #{self[:name]} remove 2>&1}
19
+ cmd = %{update-rc.d -n -f #{self[:name]} remove 2>&1}
20
+ self.debug "Executing 'enabled' test: '%s'" % cmd
21
+ output = %x{#{cmd}}
18
22
  unless $? == 0
19
23
  raise Puppet::Error, "Could not check %s: %s" %
20
24
  [self.name, output]
@@ -30,7 +34,9 @@ Puppet.type(:service).newsvctype(:debian, :init) do
30
34
  end
31
35
 
32
36
  def enable
33
- output = %x{update-rc.d #{self[:name]} defaults 2>&1}
37
+ cmd = %{update-rc.d #{self[:name]} defaults 2>&1}
38
+ self.debug "Executing '%s'" % cmd
39
+ output = %x{#{cmd}}
34
40
 
35
41
  unless $? == 0
36
42
  raise Puppet::Error, "Could not enable %s: %s" %
@@ -1,54 +1,63 @@
1
1
  # The standard init-based service type. Many other service types are
2
2
  # customizations of this module.
3
3
  Puppet.type(:service).newsvctype(:init) do
4
-
5
- # Set the default init directory.
6
- Puppet.type(:service).attrclass(:path).defaultto do
4
+ def self.defpath
7
5
  case Facter["operatingsystem"].value
8
6
  when "FreeBSD":
9
7
  "/etc/rc.d"
10
8
  else
11
- #@defaultrc = "/etc/rc%s.d"
12
9
  "/etc/init.d"
13
10
  end
14
11
  end
15
- # # Make sure we've got a search path set up. If they don't
16
- # # specify one, try to determine one.
17
- # def configchk
18
- # unless defined? @searchpaths
19
- # Puppet.notice "Initting search paths"
20
- # @searchpaths = []
21
- # end
22
- # unless @searchpaths.length > 0
23
- # if init = self.defaultinit
24
- # self.notice "Adding default init"
25
- # @searchpaths << init
26
- # else
27
- # self.notice "No default init for %s" %
28
- # Facter["operatingsystem"].value
29
- #
30
- # raise Puppet::Error.new(
31
- # "You must specify a valid search path for service %s" %
32
- # self.name
33
- # )
34
- # end
35
- # end
36
- # end
37
- #
38
- # # Get the default init path.
39
- # def defaultinit
40
- # unless defined? @defaultinit
41
- # case Facter["operatingsystem"].value
42
- # when "FreeBSD":
43
- # @defaultinit = "/etc/rc.d"
44
- # else
45
- # @defaultinit = "/etc/init.d"
46
- # @defaultrc = "/etc/rc%s.d"
47
- # end
48
- # end
49
- #
50
- # return @defaultinit
51
- # end
12
+
13
+ Puppet.type(:service).newpath(:init, defpath())
14
+
15
+ # Set the default init directory.
16
+ Puppet.type(:service).attrclass(:path).defaultto defpath()
17
+
18
+ # List all services of this type. This has to be an instance method
19
+ # so that it's inherited by submodules.
20
+ def list(name)
21
+ # We need to find all paths specified for our type or any parent types
22
+ paths = Puppet.type(:service).paths(name)
23
+
24
+ # Now see if there are any included modules
25
+ included_modules.each do |mod|
26
+ next unless mod.respond_to? :name
27
+
28
+ mname = mod.name
29
+
30
+ if mpaths = Puppet.type(:service).paths(mname) and ! mpaths.empty?
31
+ paths += mpaths
32
+ end
33
+ end
34
+
35
+ paths.each do |path|
36
+ unless FileTest.directory?(path)
37
+ Puppet.notice "Service path %s does not exist" % path
38
+ next
39
+ end
40
+
41
+ check = [:ensure]
42
+
43
+ if public_method_defined? :enabled?
44
+ check << :enable
45
+ end
46
+
47
+ Dir.entries(path).reject { |e|
48
+ fullpath = File.join(path, e)
49
+ e =~ /^\./ or ! FileTest.executable?(fullpath)
50
+ }.each do |name|
51
+ if obj = Puppet::Type.type(:service)[name]
52
+ obj[:check] = check
53
+ else
54
+ Puppet::Type.type(:service).create(
55
+ :name => name, :check => check, :path => path
56
+ )
57
+ end
58
+ end
59
+ end
60
+ end
52
61
 
53
62
  # Mark that our init script supports 'status' commands.
54
63
  def hasstatus=(value)
@@ -89,20 +98,6 @@ Puppet.type(:service).newsvctype(:init) do
89
98
  end
90
99
  end
91
100
 
92
- # Enable a service, so it's started at boot time. This basically
93
- # just creates links in the RC directories, which means that, well,
94
- # we need to know where the rc directories are.
95
- # FIXME This should probably be a state or something, and
96
- # it should actually create use Symlink objects...
97
- # At this point, people should just link objects for enabling,
98
- # if they're running on a system that doesn't have a tool to
99
- # manage init script links.
100
- #def enable
101
- #end
102
-
103
- #def disable
104
- #end
105
-
106
101
  def search(name)
107
102
  self[:path].each { |path|
108
103
  fqname = File.join(path,name)
@@ -142,4 +137,4 @@ Puppet.type(:service).newsvctype(:init) do
142
137
  end
143
138
  end
144
139
 
145
- # $Id: init.rb 922 2006-02-16 19:10:34Z luke $
140
+ # $Id: init.rb 1125 2006-04-20 19:38:48Z luke $
@@ -1,11 +1,20 @@
1
1
  # Solaris 10 SMF-style services.
2
2
  Puppet.type(:service).newsvctype(:smf) do
3
3
  def enable
4
- "svcadm enable %s" % self[:name]
4
+ self.start
5
5
  end
6
6
 
7
- def dsiable
8
- "svcadm disable %s" % self[:name]
7
+ def enabled?
8
+ case self.status
9
+ when :running:
10
+ return :true
11
+ else
12
+ return :false
13
+ end
14
+ end
15
+
16
+ def disable
17
+ self.stop
9
18
  end
10
19
 
11
20
  def restartcmd
@@ -51,8 +60,9 @@ Puppet.type(:service).newsvctype(:smf) do
51
60
  }
52
61
 
53
62
  if $? != 0
54
- raise Puppet::Error,
55
- "Could not get status on service %s" % self.name
63
+ #raise Puppet::Error,
64
+ warning "Could not get status on service %s" % self.name
65
+ return :stopped
56
66
  end
57
67
  end
58
68
 
@@ -61,4 +71,4 @@ Puppet.type(:service).newsvctype(:smf) do
61
71
  end
62
72
  end
63
73
 
64
- # $Id: smf.rb 938 2006-02-24 20:01:01Z luke $
74
+ # $Id: smf.rb 1113 2006-04-17 16:15:33Z luke $
@@ -19,25 +19,49 @@ class State < Puppet::Parameter
19
19
  attr_accessor :unmanaged
20
20
  attr_reader :name
21
21
 
22
- #def inspect
23
- # "State(%s)" % self.name
24
- #end
22
+ def checkable
23
+ @checkable = true
24
+ end
25
+
26
+ def uncheckable
27
+ @checkable = false
28
+ end
29
+
30
+ def checkable?
31
+ if defined? @checkable
32
+ return @checkable
33
+ else
34
+ return true
35
+ end
36
+ end
37
+ end
25
38
 
26
- #def to_s
27
- # self.inspect
28
- #end
39
+ # Create the value management variables.
40
+ def self.initvars
41
+ @parametervalues = {}
42
+ @aliasvalues = {}
43
+ @parameterregexes = {}
29
44
  end
30
45
 
31
- # Parameters just use 'newvalues', since there's no work associated with them.
46
+ # Parameters just use 'newvalues', since there's no work associated with them,
47
+ # but states have blocks associated with their allowed values.
32
48
  def self.newvalue(name, &block)
33
- @parametervalues ||= {}
49
+ name = name.intern if name.is_a? String
34
50
 
35
- if @parametervalues.include?(name)
36
- Puppet.warning "%s already has a value for %s" % [name, name]
37
- end
38
- @parametervalues[name] = block
51
+ case name
52
+ when Symbol
53
+ if @parametervalues.include?(name)
54
+ Puppet.warning "%s reassigning value %s" % [self.name, name]
55
+ end
56
+ @parametervalues[name] = block
39
57
 
40
- define_method("set_" + name.to_s, &block)
58
+ define_method("set_" + name.to_s, &block)
59
+ when Regexp
60
+ @parameterregexes[name] = block
61
+ else
62
+ raise ArgumentError, "Invalid value %s of type %s" %
63
+ [name, name.class]
64
+ end
41
65
  end
42
66
 
43
67
  # Call the method associated with a given value.
@@ -49,32 +73,43 @@ class State < Puppet::Parameter
49
73
 
50
74
  value = self.should
51
75
  method = "set_" + value.to_s
52
- unless self.respond_to?(method)
53
- self.fail "%s is not a valid value for %s" %
54
- [value, self.class.name]
55
- end
56
- self.debug "setting %s (currently %s)" % [value, self.is]
76
+ event = nil
77
+ if self.respond_to?(method)
78
+ self.debug "setting %s (currently %s)" % [value, self.is]
57
79
 
58
- begin
59
- event = self.send(method)
60
- rescue Puppet::Error
61
- raise
62
- rescue => detail
63
- if Puppet[:debug]
64
- puts detail.backtrace
80
+ begin
81
+ event = self.send(method)
82
+ rescue Puppet::Error
83
+ raise
84
+ rescue => detail
85
+ if Puppet[:debug]
86
+ puts detail.backtrace
87
+ end
88
+ self.fail "Could not set %s on %s: %s" %
89
+ [value, self.class.name, detail]
65
90
  end
66
- self.fail "Could not set %s on %s: %s" %
67
- [value, self.class.name, detail]
91
+ elsif ary = self.class.match?(value)
92
+ # FIXME It'd be better here to define a method, so that
93
+ # the blocks could return values.
94
+ event = self.instance_eval(&ary[1])
95
+ else
96
+ self.fail "%s is not a valid value for %s" %
97
+ [value, self.class.name]
68
98
  end
69
99
 
70
100
  if event and event.is_a?(Symbol)
71
- return event
101
+ if event == :nochange
102
+ return nil
103
+ else
104
+ return event
105
+ end
72
106
  else
73
107
  # Return the appropriate event.
74
108
  event = case self.should
75
109
  when :present: (@parent.class.name.to_s + "_created").intern
76
110
  when :absent: (@parent.class.name.to_s + "_removed").intern
77
111
  else
112
+ warning self.should.inspect
78
113
  (@parent.class.name.to_s + "_changed").intern
79
114
  end
80
115
 
@@ -106,8 +141,8 @@ class State < Puppet::Parameter
106
141
 
107
142
  def inspect
108
143
  str = "State('%s', " % self.name
109
- if defined? @is and @is
110
- str += "@is = '%s', " % @is
144
+ if self.is
145
+ str += "@is = '%s', " % [self.is]
111
146
  else
112
147
  str += "@is = nil, "
113
148
  end
@@ -186,7 +221,11 @@ class State < Puppet::Parameter
186
221
  # return the full path to us, for logging and rollback; not currently
187
222
  # used
188
223
  def path
189
- return [@parent.path, self.name].join("/")
224
+ if defined? @parent and @parent
225
+ return [@parent.path, self.name].join("/")
226
+ else
227
+ return self.name
228
+ end
190
229
  end
191
230
 
192
231
  # Only return the first value
@@ -352,4 +391,4 @@ class State < Puppet::Parameter
352
391
  end
353
392
  end
354
393
 
355
- # $Id: state.rb 912 2006-02-15 18:23:33Z luke $
394
+ # $Id: state.rb 1124 2006-04-20 07:00:10Z luke $
@@ -4,7 +4,8 @@ require 'puppet/type/pfile'
4
4
 
5
5
  module Puppet
6
6
  newtype(:symlink) do
7
- @doc = "Create symbolic links to existing files."
7
+ @doc = "Create symbolic links to existing files. **This type is deprecated;
8
+ use file_ instead.**"
8
9
  #newstate(:ensure) do
9
10
  ensurable do
10
11
  require 'etc'
@@ -65,7 +66,7 @@ module Puppet
65
66
  end
66
67
 
67
68
  # this is somewhat complicated, because it could exist and be
68
- # a file
69
+ # a link
69
70
  def sync
70
71
  case self.should
71
72
  when :absent
@@ -109,7 +110,7 @@ module Puppet
109
110
  # in /opt/csw; link it into /usr/local
110
111
  symlink { \"/usr/local\":
111
112
  ensure => \"/opt/csw\",
112
- recurse => 1
113
+ recurse => true
113
114
  }
114
115
 
115
116
 
@@ -120,13 +121,16 @@ module Puppet
120
121
  @stat = nil
121
122
  @target = @parent.state(:ensure).should
122
123
 
124
+ self.setparent(@target)
125
+ end
126
+
127
+ def setparent(value)
123
128
  # we want to remove our state, because we're creating children
124
129
  # to do the links
125
130
  if FileTest.exist?(@target)
126
- @stat = File.stat(@target)
131
+ @stat = File.lstat(@target)
127
132
  else
128
- @parent.info "Target %s must exist for recursive links" %
129
- @target
133
+ @setparent = false
130
134
  return
131
135
  end
132
136
 
@@ -168,6 +172,7 @@ module Puppet
168
172
  dir = Puppet.type(:file).implicitcreate(args)
169
173
  dir.parent = @parent
170
174
  @parent.push dir
175
+ @setparent = true
171
176
  end
172
177
  end
173
178
 
@@ -179,4 +184,4 @@ module Puppet
179
184
  end # Puppet.type(:symlink)
180
185
  end
181
186
 
182
- # $Id: symlink.rb 922 2006-02-16 19:10:34Z luke $
187
+ # $Id: symlink.rb 1098 2006-04-10 22:13:10Z luke $
@@ -157,6 +157,10 @@ module Puppet
157
157
  validate do
158
158
  end
159
159
 
160
+ def self.list
161
+ self.collect { |t| t }
162
+ end
163
+
160
164
  @depthfirst = true
161
165
 
162
166
  def initialize(hash)
@@ -183,4 +187,4 @@ module Puppet
183
187
  end
184
188
  end
185
189
 
186
- # $Id: tidy.rb 841 2006-01-18 17:24:15Z luke $
190
+ # $Id: tidy.rb 1125 2006-04-20 19:38:48Z luke $
@@ -19,6 +19,27 @@ module Puppet
19
19
 
20
20
  newstate(:ensure, @parentstate) do
21
21
  newvalue(:present) do
22
+ # Verify that they have provided everything necessary, if we
23
+ # are trying to manage the user
24
+ if @parent.managed?
25
+ @parent.class.states.each { |state|
26
+ next if stateobj = @parent.state(state.name)
27
+ next if state.name == :ensure
28
+
29
+ unless state.autogen? or state.isoptional?
30
+ if state.method_defined?(:autogen)
31
+ @parent[state.name] = :auto
32
+ else
33
+ @parent.fail "Users require a value for %s" %
34
+ state.name
35
+ end
36
+ end
37
+ }
38
+
39
+ #if @states.empty?
40
+ # @parent[:comment] = @parent[:name]
41
+ #end
42
+ end
22
43
  self.syncname(:present)
23
44
  end
24
45
 
@@ -198,6 +219,76 @@ module Puppet
198
219
  isautogen
199
220
  end
200
221
 
222
+ newstate(:groups, @parentstate) do
223
+ desc "The groups of which the user is a member. The primary
224
+ group should not be listed. Multiple groups should be
225
+ specified as an array."
226
+
227
+ isoptional
228
+
229
+ def should_to_s
230
+ self.should
231
+ end
232
+
233
+ def is_to_s
234
+ @is.join(",")
235
+ end
236
+
237
+ # We need to override this because the groups need to
238
+ # be joined with commas
239
+ def should
240
+ unless defined? @is
241
+ retrieve
242
+ end
243
+
244
+ @should ||= []
245
+
246
+ if @parent[:membership] == :inclusive
247
+ @should.sort.join(",")
248
+ else
249
+ (@is + @should).uniq.sort.join(",")
250
+ end
251
+ end
252
+
253
+ def retrieve
254
+ @is = grouplist()
255
+ end
256
+
257
+ def insync?
258
+ unless defined? @should and @should
259
+ return false
260
+ end
261
+ unless defined? @is and @is
262
+ return false
263
+ end
264
+ return @is.sort == @should.sort
265
+ end
266
+
267
+ validate do |value|
268
+ if value =~ /^\d+$/
269
+ raise ArgumentError, "Group names must be provided, not numbers"
270
+ end
271
+ end
272
+
273
+ def sync
274
+ if respond_to? :setgrouplist
275
+ groups = nil
276
+ if @parent[:membership] == :inclusive
277
+ groups = @should
278
+ else
279
+ groups = (@is + @should).uniq
280
+ end
281
+
282
+ # Pass them the group list, so that the :membership logic
283
+ # is all in this class, not in parent classes.
284
+ setgrouplist(groups)
285
+ return :user_modified
286
+ else
287
+ super
288
+ end
289
+ end
290
+ end
291
+
201
292
  # these three states are all implemented differently on each platform,
202
293
  # so i'm disabling them for now
203
294
 
@@ -230,6 +321,16 @@ module Puppet
230
321
  isnamevar
231
322
  end
232
323
 
324
+ newparam(:membership) do
325
+ desc "Whether specified groups should be treated as the only groups
326
+ of which the user is a member or whether they should merely
327
+ be treated as the minimum membership list."
328
+
329
+ newvalues(:inclusive, :minimum)
330
+
331
+ defaultto :minimum
332
+ end
333
+
233
334
  @doc = "Manage users. Currently can create and modify users, but
234
335
  cannot delete them. Theoretically all of the parameters are
235
336
  optional, but if no parameters are specified the comment will
@@ -287,6 +388,18 @@ module Puppet
287
388
  end
288
389
  end
289
390
 
391
+ # List all found users
392
+ def self.listbyname
393
+ users = []
394
+ Etc.setpwent
395
+ while ent = Etc.getpwent
396
+ users << ent.name
397
+ end
398
+ Etc.endpwent
399
+
400
+ return users
401
+ end
402
+
290
403
  def exists?
291
404
  self.class.parentmodule.exists?(self)
292
405
  end
@@ -307,25 +420,8 @@ module Puppet
307
420
  @userinfo = nil
308
421
  super
309
422
 
310
- # Verify that they have provided everything necessary, if we
311
- # are trying to manage the user
312
- if self.managed?
313
- self.class.states.each { |state|
314
- next if @states.include?(state.name)
315
- next if state.name == :ensure
316
-
317
- unless state.autogen? or state.isoptional?
318
- if state.method_defined?(:autogen)
319
- self[state.name] = :auto
320
- else
321
- self.fail "Users require a value for %s" % state.name
322
- end
323
- end
324
- }
325
-
326
- if @states.empty?
327
- self[:comment] = self[:name]
328
- end
423
+ unless defined? @states
424
+ raise "wtf?"
329
425
  end
330
426
  end
331
427
 
@@ -345,4 +441,4 @@ module Puppet
345
441
  end
346
442
  end
347
443
 
348
- # $Id: user.rb 966 2006-03-02 17:12:26Z luke $
444
+ # $Id: user.rb 1125 2006-04-20 19:38:48Z luke $