puppet 2.6.1 → 2.6.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.
- data/CHANGELOG +51 -195
- data/LICENSE +2 -2
- data/conf/suse/puppet.spec +13 -10
- data/install.rb +7 -13
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application.rb +17 -21
- data/lib/puppet/defaults.rb +1 -1
- data/lib/puppet/dsl.rb +0 -4
- data/lib/puppet/dsl/resource_type_api.rb +16 -10
- data/lib/puppet/external/event-loop/event-loop.rb +15 -11
- data/lib/puppet/feature/base.rb +2 -1
- data/lib/puppet/feature/rails.rb +1 -3
- data/lib/puppet/network/http/webrick/rest.rb +1 -0
- data/lib/puppet/network/http_pool.rb +0 -12
- data/lib/puppet/parser/ast/function.rb +1 -1
- data/lib/puppet/parser/ast/resource.rb +1 -5
- data/lib/puppet/parser/functions/extlookup.rb +1 -1
- data/lib/puppet/parser/functions/versioncmp.rb +3 -3
- data/lib/puppet/parser/lexer.rb +1 -1
- data/lib/puppet/parser/parser_support.rb +4 -2
- data/lib/puppet/parser/resource.rb +8 -0
- data/lib/puppet/parser/type_loader.rb +50 -48
- data/lib/puppet/provider/nameservice.rb +1 -0
- data/lib/puppet/provider/nameservice/objectadd.rb +2 -1
- data/lib/puppet/provider/service/freebsd.rb +1 -1
- data/lib/puppet/provider/service/launchd.rb +16 -9
- data/lib/puppet/provider/ssh_authorized_key/parsed.rb +7 -0
- data/lib/puppet/provider/user/hpux.rb +0 -1
- data/lib/puppet/provider/user/user_role_add.rb +21 -9
- data/lib/puppet/provider/user/useradd.rb +44 -3
- data/lib/puppet/rails.rb +3 -3
- data/lib/puppet/reference/configuration.rb +7 -12
- data/lib/puppet/reference/indirection.rb +2 -2
- data/lib/puppet/reference/metaparameter.rb +10 -9
- data/lib/puppet/reference/type.rb +6 -6
- data/lib/puppet/reports/rrdgraph.rb +1 -1
- data/lib/puppet/reports/tagmail.rb +1 -1
- data/lib/puppet/ssl/certificate_request.rb +1 -1
- data/lib/puppet/sslcertificates/ca.rb +4 -10
- data/lib/puppet/type.rb +3 -3
- data/lib/puppet/type/cron.rb +1 -1
- data/lib/puppet/type/tidy.rb +1 -0
- data/lib/puppet/type/user.rb +55 -0
- data/lib/puppet/type/whit.rb +4 -0
- data/lib/puppet/util.rb +8 -0
- data/lib/puppet/util/metric.rb +38 -9
- data/lib/puppet/util/rdoc/parser.rb +10 -7
- data/lib/puppet/util/reference.rb +4 -4
- data/lib/puppet/util/zaml.rb +0 -1
- data/spec/fixtures/yaml/report0.25.x.yaml +64 -0
- data/spec/fixtures/yaml/report2.6.x.yaml +190 -0
- data/spec/integration/application/doc_spec.rb +55 -0
- data/spec/integration/defaults_spec.rb +1 -1
- data/spec/integration/parser/compiler_spec.rb +21 -0
- data/spec/integration/parser/ruby_manifest_spec.rb +128 -0
- data/spec/lib/puppet_spec/files.rb +1 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/application_spec.rb +16 -25
- data/spec/unit/dsl/resource_type_api_spec.rb +32 -12
- data/spec/unit/indirector/node/active_record_spec.rb +0 -1
- data/spec/unit/parser/ast/function_spec.rb +14 -4
- data/spec/unit/parser/lexer_spec.rb +8 -0
- data/spec/unit/parser/parser_spec.rb +0 -9
- data/spec/unit/parser/type_loader_spec.rb +3 -16
- data/spec/unit/provider/service/launchd_spec.rb +8 -5
- data/spec/unit/provider/user/user_role_add_spec.rb +18 -1
- data/spec/unit/provider/user/useradd_spec.rb +19 -0
- data/spec/unit/rails_spec.rb +10 -4
- data/spec/unit/reports/rrdgraph_spec.rb +31 -0
- data/spec/unit/reports/tagmail_spec.rb +1 -0
- data/spec/unit/sslcertificates/ca_spec.rb +110 -0
- data/spec/unit/type/user_spec.rb +19 -1
- data/spec/unit/type/whit_spec.rb +11 -0
- data/spec/unit/type_spec.rb +7 -0
- data/spec/unit/util/rdoc/parser_spec.rb +18 -14
- data/spec/unit/util/zaml_spec.rb +2 -1
- metadata +11 -6
- data/conf/suse/ruby-env.patch +0 -17
- data/test/certmgr/ca.rb +0 -87
@@ -64,6 +64,7 @@ class Puppet::Parser::Resource < Puppet::Resource
|
|
64
64
|
|
65
65
|
# Retrieve the associated definition and evaluate it.
|
66
66
|
def evaluate
|
67
|
+
return if evaluated?
|
67
68
|
@evaluated = true
|
68
69
|
if klass = resource_type and ! builtin_type?
|
69
70
|
finish
|
@@ -93,6 +94,7 @@ class Puppet::Parser::Resource < Puppet::Resource
|
|
93
94
|
@finished = true
|
94
95
|
add_defaults
|
95
96
|
add_metaparams
|
97
|
+
add_scope_tags
|
96
98
|
validate
|
97
99
|
end
|
98
100
|
|
@@ -259,6 +261,12 @@ class Puppet::Parser::Resource < Puppet::Resource
|
|
259
261
|
end
|
260
262
|
end
|
261
263
|
|
264
|
+
def add_scope_tags
|
265
|
+
if scope_resource = scope.resource
|
266
|
+
tag(*scope_resource.tags)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
262
270
|
# Accept a parameter from an override.
|
263
271
|
def override_parameter(param)
|
264
272
|
# This can happen if the override is defining a new parameter, rather
|
@@ -3,25 +3,56 @@ require 'puppet/node/environment'
|
|
3
3
|
class Puppet::Parser::TypeLoader
|
4
4
|
include Puppet::Node::Environment::Helper
|
5
5
|
|
6
|
-
|
6
|
+
# Helper class that makes sure we don't try to import the same file
|
7
|
+
# more than once from either the same thread or different threads.
|
8
|
+
class Helper
|
7
9
|
include MonitorMixin
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def initialize
|
11
|
+
super
|
12
|
+
# These hashes are indexed by filename
|
13
|
+
@state = {} # :doing or :done
|
14
|
+
@thread = {} # if :doing, thread that's doing the parsing
|
15
|
+
@cond_var = {} # if :doing, condition var that will be signaled when done.
|
12
16
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
|
18
|
+
# Execute the supplied block exactly once per file, no matter how
|
19
|
+
# many threads have asked for it to run. If another thread is
|
20
|
+
# already executing it, wait for it to finish. If this thread is
|
21
|
+
# already executing it, return immediately without executing the
|
22
|
+
# block.
|
23
|
+
#
|
24
|
+
# Note: the reason for returning immediately if this thread is
|
25
|
+
# already executing the block is to handle the case of a circular
|
26
|
+
# import--when this happens, we attempt to recursively re-parse a
|
27
|
+
# file that we are already in the process of parsing. To prevent
|
28
|
+
# an infinite regress we need to simply do nothing when the
|
29
|
+
# recursive import is attempted.
|
30
|
+
def do_once(file)
|
31
|
+
need_to_execute = synchronize do
|
32
|
+
case @state[file]
|
33
|
+
when :doing
|
34
|
+
if @thread[file] != Thread.current
|
35
|
+
@cond_var[file].wait
|
36
|
+
end
|
37
|
+
false
|
38
|
+
when :done
|
39
|
+
false
|
20
40
|
else
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
41
|
+
@state[file] = :doing
|
42
|
+
@thread[file] = Thread.current
|
43
|
+
@cond_var[file] = new_cond
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
if need_to_execute
|
48
|
+
begin
|
49
|
+
yield
|
50
|
+
ensure
|
51
|
+
synchronize do
|
52
|
+
@state[file] = :done
|
53
|
+
@thread.delete(file)
|
54
|
+
@cond_var.delete(file).broadcast
|
55
|
+
end
|
25
56
|
end
|
26
57
|
end
|
27
58
|
end
|
@@ -51,8 +82,7 @@ class Puppet::Parser::TypeLoader
|
|
51
82
|
unless file =~ /^#{File::SEPARATOR}/
|
52
83
|
file = File.join(dir, file)
|
53
84
|
end
|
54
|
-
|
55
|
-
@imported[file] = true
|
85
|
+
@loading_helper.do_once(file) do
|
56
86
|
parse_file(file)
|
57
87
|
end
|
58
88
|
end
|
@@ -60,27 +90,20 @@ class Puppet::Parser::TypeLoader
|
|
60
90
|
modname
|
61
91
|
end
|
62
92
|
|
63
|
-
def imported?(file)
|
64
|
-
@imported.has_key?(file)
|
65
|
-
end
|
66
|
-
|
67
93
|
def known_resource_types
|
68
94
|
environment.known_resource_types
|
69
95
|
end
|
70
96
|
|
71
97
|
def initialize(env)
|
72
98
|
self.environment = env
|
73
|
-
@
|
74
|
-
@loading = Helper.new
|
75
|
-
|
76
|
-
@imported = {}
|
99
|
+
@loading_helper = Helper.new
|
77
100
|
end
|
78
101
|
|
79
102
|
def load_until(namespaces, name)
|
80
103
|
return nil if name == "" # special-case main.
|
81
104
|
name2files(namespaces, name).each do |filename|
|
82
105
|
modname = begin
|
83
|
-
|
106
|
+
import(filename)
|
84
107
|
rescue Puppet::ImportError => detail
|
85
108
|
# We couldn't load the item
|
86
109
|
# I'm not convienced we should just drop these errors, but this
|
@@ -96,10 +119,6 @@ class Puppet::Parser::TypeLoader
|
|
96
119
|
nil
|
97
120
|
end
|
98
121
|
|
99
|
-
def loaded?(name)
|
100
|
-
@loaded.include?(name)
|
101
|
-
end
|
102
|
-
|
103
122
|
def name2files(namespaces, name)
|
104
123
|
return [name.sub(/^::/, '').gsub("::", File::SEPARATOR)] if name =~ /^::/
|
105
124
|
|
@@ -126,21 +145,4 @@ class Puppet::Parser::TypeLoader
|
|
126
145
|
parser.file = file
|
127
146
|
parser.parse
|
128
147
|
end
|
129
|
-
|
130
|
-
# Utility method factored out of load for handling thread-safety.
|
131
|
-
# This isn't tested in the specs, because that's basically impossible.
|
132
|
-
def import_if_possible(file, current_file = nil)
|
133
|
-
@loaded[file] || begin
|
134
|
-
case @loading.owner_of(file)
|
135
|
-
when :this_thread
|
136
|
-
nil
|
137
|
-
when :another_thread
|
138
|
-
import_if_possible(file,current_file)
|
139
|
-
when :nobody
|
140
|
-
@loaded[file] = import(file,current_file)
|
141
|
-
end
|
142
|
-
ensure
|
143
|
-
@loading.done_with(file)
|
144
|
-
end
|
145
|
-
end
|
146
148
|
end
|
@@ -165,6 +165,7 @@ class Puppet::Provider::NameService < Puppet::Provider
|
|
165
165
|
|
166
166
|
begin
|
167
167
|
execute(self.addcmd)
|
168
|
+
execute(self.passcmd) if self.feature? :manages_password_age
|
168
169
|
rescue Puppet::ExecutionFailure => detail
|
169
170
|
raise Puppet::Error, "Could not create #{@resource.class.name} #{@resource.name}: #{detail}"
|
170
171
|
end
|
@@ -13,7 +13,8 @@ class ObjectAdd < Puppet::Provider::NameService
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def modifycmd(param, value)
|
16
|
-
cmd = [command(:modify)
|
16
|
+
cmd = [command(param.to_s =~ /password_.+_age/ ? :password : :modify)]
|
17
|
+
cmd << flag(param) << value
|
17
18
|
if @resource.allowdupe? && ((param == :uid) || (param == :gid and self.class.name == :groupadd))
|
18
19
|
cmd << "-o"
|
19
20
|
end
|
@@ -78,7 +78,7 @@ Puppet::Type.type(:service).provide :freebsd, :parent => :init do
|
|
78
78
|
|
79
79
|
# Add a new setting to the rc files
|
80
80
|
def rc_add(service, rcvar, yesno)
|
81
|
-
append = "
|
81
|
+
append = "\# Added by Puppet\n#{rcvar}_enable=\"#{yesno}\"\n"
|
82
82
|
# First, try the one-file-per-service style
|
83
83
|
if File.exists?(@@rcconf_dir)
|
84
84
|
File.open(@@rcconf_dir + "/#{service}", File::WRONLY | File::APPEND | File::CREAT, 0644) {
|
@@ -38,6 +38,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
38
38
|
|
39
39
|
commands :launchctl => "/bin/launchctl"
|
40
40
|
commands :sw_vers => "/usr/bin/sw_vers"
|
41
|
+
commands :plutil => "/usr/bin/plutil"
|
41
42
|
|
42
43
|
defaultfor :operatingsystem => :darwin
|
43
44
|
confine :operatingsystem => :darwin
|
@@ -52,6 +53,12 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
52
53
|
Launchd_Overrides = "/var/db/launchd.db/com.apple.launchd/overrides.plist"
|
53
54
|
|
54
55
|
|
56
|
+
# Read a plist, whether its format is XML or in Apple's "binary1"
|
57
|
+
# format.
|
58
|
+
def self.read_plist(path)
|
59
|
+
Plist::parse_xml(plutil('-convert', 'xml1', '-o', '-', path))
|
60
|
+
end
|
61
|
+
|
55
62
|
# returns a label => path map for either all jobs, or just a single
|
56
63
|
# job if the label is specified
|
57
64
|
def self.jobsearch(label=nil)
|
@@ -62,8 +69,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
62
69
|
next if f =~ /^\..*$/
|
63
70
|
next if FileTest.directory?(f)
|
64
71
|
fullpath = File.join(path, f)
|
65
|
-
job =
|
66
|
-
if job and job.has_key?("Label")
|
72
|
+
if FileTest.file?(fullpath) and job = read_plist(fullpath) and job.has_key?("Label")
|
67
73
|
if job["Label"] == label
|
68
74
|
return { label => fullpath }
|
69
75
|
else
|
@@ -118,8 +124,11 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
118
124
|
def plist_from_label(label)
|
119
125
|
job = self.class.jobsearch(label)
|
120
126
|
job_path = job[label]
|
121
|
-
|
122
|
-
|
127
|
+
if FileTest.file?(job_path)
|
128
|
+
job_plist = self.class.read_plist(job_path)
|
129
|
+
else
|
130
|
+
raise Puppet::Error.new("Unable to parse launchd plist at path: #{job_path}")
|
131
|
+
end
|
123
132
|
[job_path, job_plist]
|
124
133
|
end
|
125
134
|
|
@@ -200,9 +209,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
200
209
|
job_plist_disabled = job_plist["Disabled"] if job_plist.has_key?("Disabled")
|
201
210
|
|
202
211
|
if self.class.get_macosx_version_major == "10.6":
|
203
|
-
overrides =
|
204
|
-
|
205
|
-
unless overrides.nil?
|
212
|
+
if FileTest.file?(Launchd_Overrides) and overrides = self.class.read_plist(Launchd_Overrides)
|
206
213
|
if overrides.has_key?(resource[:name])
|
207
214
|
overrides_disabled = overrides[resource[:name]]["Disabled"] if overrides[resource[:name]].has_key?("Disabled")
|
208
215
|
end
|
@@ -227,7 +234,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
227
234
|
# versions this is stored in the job plist itself.
|
228
235
|
def enable
|
229
236
|
if self.class.get_macosx_version_major == "10.6"
|
230
|
-
overrides =
|
237
|
+
overrides = self.class.read_plist(Launchd_Overrides)
|
231
238
|
overrides[resource[:name]] = { "Disabled" => false }
|
232
239
|
Plist::Emit.save_plist(overrides, Launchd_Overrides)
|
233
240
|
else
|
@@ -242,7 +249,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
242
249
|
|
243
250
|
def disable
|
244
251
|
if self.class.get_macosx_version_major == "10.6"
|
245
|
-
overrides =
|
252
|
+
overrides = self.class.read_plist(Launchd_Overrides)
|
246
253
|
overrides[resource[:name]] = { "Disabled" => true }
|
247
254
|
Plist::Emit.save_plist(overrides, Launchd_Overrides)
|
248
255
|
else
|
@@ -61,6 +61,13 @@ require 'puppet/provider/parsedfile'
|
|
61
61
|
Dir.mkdir(dir, dir_perm)
|
62
62
|
File.chown(uid, nil, dir)
|
63
63
|
end
|
64
|
+
|
65
|
+
# ParsedFile usually calls backup_target much later in the flush process,
|
66
|
+
# but our SUID makes that fail to open filebucket files for writing.
|
67
|
+
# Fortunately, there's already logic to make sure it only ever happens once,
|
68
|
+
# so calling it here supresses the later attempt by our superclass's flush method.
|
69
|
+
self.class.backup_target(target)
|
70
|
+
|
64
71
|
Puppet::Util::SUIDManager.asuser(@resource.should(:user)) { super }
|
65
72
|
File.chown(uid, nil, target)
|
66
73
|
File.chmod(file_perm, target)
|
@@ -6,13 +6,15 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
|
|
6
6
|
|
7
7
|
defaultfor :operatingsystem => :solaris
|
8
8
|
|
9
|
-
commands :add => "useradd", :delete => "userdel", :modify => "usermod", :role_add => "roleadd", :role_delete => "roledel", :role_modify => "rolemod"
|
9
|
+
commands :add => "useradd", :delete => "userdel", :modify => "usermod", :password => "chage", :role_add => "roleadd", :role_delete => "roledel", :role_modify => "rolemod"
|
10
10
|
options :home, :flag => "-d", :method => :dir
|
11
11
|
options :comment, :method => :gecos
|
12
12
|
options :groups, :flag => "-G"
|
13
13
|
options :roles, :flag => "-R"
|
14
14
|
options :auths, :flag => "-A"
|
15
15
|
options :profiles, :flag => "-P"
|
16
|
+
options :password_min_age, :flag => "-m"
|
17
|
+
options :password_max_age, :flag => "-M"
|
16
18
|
|
17
19
|
verify :gid, "GID must be an integer" do |value|
|
18
20
|
value.is_a? Integer
|
@@ -22,14 +24,14 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
|
|
22
24
|
value !~ /\s/
|
23
25
|
end
|
24
26
|
|
25
|
-
has_features :manages_homedir, :allows_duplicates, :manages_solaris_rbac, :manages_passwords
|
27
|
+
has_features :manages_homedir, :allows_duplicates, :manages_solaris_rbac, :manages_passwords, :manages_password_age
|
26
28
|
|
27
29
|
#must override this to hand the keyvalue pairs
|
28
30
|
def add_properties
|
29
31
|
cmd = []
|
30
32
|
Puppet::Type.type(:user).validproperties.each do |property|
|
31
33
|
#skip the password because we can't create it with the solaris useradd
|
32
|
-
next if [:ensure, :password].include?(property)
|
34
|
+
next if [:ensure, :password, :password_min_age, :password_max_age].include?(property)
|
33
35
|
# 1680 Now you can set the hashed passwords on solaris:lib/puppet/provider/user/user_role_add.rb
|
34
36
|
# the value needs to be quoted, mostly because -c might
|
35
37
|
# have spaces in it
|
@@ -79,6 +81,7 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
|
|
79
81
|
run(transition("normal"), "transition role to")
|
80
82
|
else
|
81
83
|
run(addcmd, "create")
|
84
|
+
run(passcmd, "change password policy for")
|
82
85
|
end
|
83
86
|
# added to handle case when password is specified
|
84
87
|
self.password = @resource[:password] if @resource[:password]
|
@@ -140,14 +143,23 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
|
|
140
143
|
run([command(:modify)] + build_keys_cmd(keys_hash) << @resource[:name], "modify attribute key pairs")
|
141
144
|
end
|
142
145
|
|
143
|
-
#Read in /etc/shadow, find the line for this user (skipping comments, because who knows) and return
|
146
|
+
#Read in /etc/shadow, find the line for this user (skipping comments, because who knows) and return it
|
144
147
|
#No abstraction, all esoteric knowledge of file formats, yay
|
148
|
+
def shadow_entry
|
149
|
+
return @shadow_entry if defined? @shadow_entry
|
150
|
+
@shadow_entry = File.readlines("/etc/shadow").reject { |r| r =~ /^[^\w]/ }.collect { |l| l.chomp.split(':') }.find { |user, _| user == @resource[:name] }
|
151
|
+
end
|
152
|
+
|
145
153
|
def password
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
154
|
+
shadow_entry[1] if shadow_entry
|
155
|
+
end
|
156
|
+
|
157
|
+
def min_age
|
158
|
+
shadow_entry ? shadow_entry[3] : :absent
|
159
|
+
end
|
160
|
+
|
161
|
+
def max_age
|
162
|
+
shadow_entry ? shadow_entry[4] : :absent
|
151
163
|
end
|
152
164
|
|
153
165
|
#Read in /etc/shadow, find the line for our used and rewrite it with the new pw
|
@@ -3,11 +3,13 @@ require 'puppet/provider/nameservice/objectadd'
|
|
3
3
|
Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameService::ObjectAdd do
|
4
4
|
desc "User management via `useradd` and its ilk. Note that you will need to install the `Shadow Password` Ruby library often known as ruby-libshadow to manage user passwords."
|
5
5
|
|
6
|
-
commands :add => "useradd", :delete => "userdel", :modify => "usermod"
|
6
|
+
commands :add => "useradd", :delete => "userdel", :modify => "usermod", :password => "chage"
|
7
7
|
|
8
8
|
options :home, :flag => "-d", :method => :dir
|
9
9
|
options :comment, :method => :gecos
|
10
10
|
options :groups, :flag => "-G"
|
11
|
+
options :password_min_age, :flag => "-m"
|
12
|
+
options :password_max_age, :flag => "-M"
|
11
13
|
|
12
14
|
verify :gid, "GID must be an integer" do |value|
|
13
15
|
value.is_a? Integer
|
@@ -17,9 +19,9 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
17
19
|
value !~ /\s/
|
18
20
|
end
|
19
21
|
|
20
|
-
has_features :manages_homedir, :allows_duplicates
|
22
|
+
has_features :manages_homedir, :allows_duplicates, :manages_expiry
|
21
23
|
|
22
|
-
|
24
|
+
has_features :manages_passwords, :manages_password_age if Puppet.features.libshadow?
|
23
25
|
|
24
26
|
def check_allow_dup
|
25
27
|
@resource.allowdupe? ? ["-o"] : []
|
@@ -35,10 +37,20 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
35
37
|
cmd
|
36
38
|
end
|
37
39
|
|
40
|
+
def check_manage_expiry
|
41
|
+
cmd = []
|
42
|
+
if @resource[:expiry]
|
43
|
+
cmd << "-e #{@resource[:expiry]}"
|
44
|
+
end
|
45
|
+
|
46
|
+
cmd
|
47
|
+
end
|
48
|
+
|
38
49
|
def add_properties
|
39
50
|
cmd = []
|
40
51
|
Puppet::Type.type(:user).validproperties.each do |property|
|
41
52
|
next if property == :ensure
|
53
|
+
next if property.to_s =~ /password_.+_age/
|
42
54
|
# the value needs to be quoted, mostly because -c might
|
43
55
|
# have spaces in it
|
44
56
|
if value = @resource.should(property) and value != ""
|
@@ -53,9 +65,38 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
|
|
53
65
|
cmd += add_properties
|
54
66
|
cmd += check_allow_dup
|
55
67
|
cmd += check_manage_home
|
68
|
+
cmd += check_manage_expiry
|
56
69
|
cmd << @resource[:name]
|
57
70
|
end
|
58
71
|
|
72
|
+
def passcmd
|
73
|
+
cmd = [command(:password)]
|
74
|
+
[:password_min_age, :password_max_age].each do |property|
|
75
|
+
if value = @resource.should(property)
|
76
|
+
cmd << flag(property) << value
|
77
|
+
end
|
78
|
+
end
|
79
|
+
cmd << @resource[:name]
|
80
|
+
end
|
81
|
+
|
82
|
+
def min_age
|
83
|
+
if Puppet.features.libshadow?
|
84
|
+
if ent = Shadow::Passwd.getspnam(@resource.name)
|
85
|
+
return ent.sp_min
|
86
|
+
end
|
87
|
+
end
|
88
|
+
:absent
|
89
|
+
end
|
90
|
+
|
91
|
+
def max_age
|
92
|
+
if Puppet.features.libshadow?
|
93
|
+
if ent = Shadow::Passwd.getspnam(@resource.name)
|
94
|
+
return ent.sp_max
|
95
|
+
end
|
96
|
+
end
|
97
|
+
:absent
|
98
|
+
end
|
99
|
+
|
59
100
|
# Retrieve the password using the Shadow Password library
|
60
101
|
def password
|
61
102
|
if Puppet.features.libshadow?
|