-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathusermod.rb
135 lines (117 loc) · 4.21 KB
/
usermod.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
require 'puppet/provider/group/groupadd'
Puppet::Type.type(:group).provide :usermod, :parent => Puppet::Type::Group::ProviderGroupadd do
require 'shellwords'
desc <<-EOM
Group management via `usermod`. This allows for local group
management when the users exist in a remote system.
EOM
commands :addmember => 'usermod',
:delmember => 'usermod',
:modmember => 'gpasswd' #TODO: is there any alternative?
has_feature :manages_members unless %w{HP-UX}.include? Facter.value(:operatingsystem)
has_feature :libuser if Puppet.features.libuser?
def addcmd
# This pulls in the main group add command should the group need
# to be added from scratch.
cmd = Array(super.map{|x| x = "#{x}"}.shelljoin)
@resource[:members] and cmd += @resource[:members].map do |x|
m = x.match /(.*):primary$/
if m.nil?
[ command(:addmember),'-aG', @resource[:name], x ].shelljoin
else
# set primary group
[ command(:addmember),'-g', @resource[:name], m[1] ].shelljoin
end
end
# A bit hacky way how to update /etc/group in a single shell session
# Executing [ 'groupadd somegrp', 'gpasswd -a user somegrp'] does not modify
# /etc/group in current session (two Puppet runs are required).
# see: https://github.com/deric/puppet-accounts/issues/60
if @resource[:members] and @resource[:members].size == 1
user = @resource[:members].first
unless user =~ /:primary$/
cmd << "sed -i.bak -e 's/^\\(#{user}\\)\\(.*\\)/\\1\\2#{user}/g' /etc/group"
end
end
mod_group(cmd)
# We're returning /bin/true here since the Nameservice classes
# would execute whatever is returned here.
return '/bin/true'
end
# This is a repeat from puppet/provider/nameservice/objectadd.
# The self.class.name matches are hard coded so cannot be easily
# overridden.
def modifycmd(param, value)
cmd = [command(param.to_s =~ /password_.+_age/ ? :password : :modify)]
cmd << flag(param) << value
if @resource.allowdupe? and (param == :gid)
cmd << "-o"
end
cmd << @resource[:name]
cmd
end
def members
getinfo(true) if @objectinfo.nil?
retval = @objectinfo.mem
if ( @resource[:attribute_membership] == :minimum ) and !retval.nil? and
!@resource[:members].nil? and (@resource[:members] - retval).empty?
then
retval = @resource[:members]
else
retval = @objectinfo.mem
end
retval.sort
end
def members=(members)
cmd = []
to_be_added = members.dup.sort!
if @resource[:attribute_membership] == :minimum
to_be_added = to_be_added | @objectinfo.mem
not to_be_added.empty? and cmd += to_be_added.map do |x|
m = x.match /(.*):primary$/
if m.nil?
[ command(:addmember),'-aG',@resource[:name],x ].shelljoin
else
[ command(:addmember),'-g',@resource[:name],m[1] ].shelljoin
end
end
mod_group(cmd)
else
# inclusive strategy
# assuming that provided members are complete set
users = []
to_be_added.each do |x|
users << x unless x =~ /:primary$/
end
unless users.empty?
cmd << [ command(:modmember),'-M',users.join(','), @resource[:name] ].shelljoin
mod_group(cmd)
end
end
end
private
# This define takes an array of commands to run and executes them in
# order to modify the group memberships on the system.
# A useful warning message is output if there is an issue modifying
# the group but all members that can be added are added. This is an
# attempt to do the "right thing" without actually breaking a run
# or creating a whole new type just to override an insignificant
# segment of the native group type.
#
# The run of the type *will* succeed in this case but fail in all
# others.
def mod_group(cmds)
cmds.each do |run_cmd|
begin
execute(run_cmd,{:custom_environment => @custom_environment, :failonfail => true, :combine => true})
rescue Puppet::ExecutionFailure => e
if $?.exitstatus == 3 then
Puppet.warning("Modifying #{@resource[:name]} => #{e}")
else
raise e
end
end
Puppet.debug("Success: #{run_cmd}")
end
end
end