Skip to content

Commit a68b924

Browse files
committed
CHEF-776 - users and groups for mac os x
1 parent a367b06 commit a68b924

5 files changed

Lines changed: 1646 additions & 1 deletion

File tree

‎chef/lib/chef/platform.rb‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ class Platform
2929
@platforms = {
3030
:mac_os_x => {
3131
:default => {
32-
:package => Chef::Provider::Package::Macports
32+
:package => Chef::Provider::Package::Macports,
33+
:user => Chef::Provider::User::Dscl,
34+
:group => Chef::Provider::Group::Dscl
3335
}
3436
},
3537
:freebsd => {
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#
2+
# Author:: Dreamcat4 (<dreamcat4@gmail.com>)
3+
# Copyright:: Copyright (c) 2009 OpsCode, Inc.
4+
# License:: Apache License, Version 2.0
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
class Chef
20+
class Provider
21+
class Group
22+
class Dscl < Chef::Provider::Group
23+
24+
def dscl(*args)
25+
host = "."
26+
stdout_result = ""; stderr_result = ""; cmd = "dscl #{host} -#{args.join(' ')}"
27+
status = popen4(cmd) do |pid, stdin, stdout, stderr|
28+
stdout.each { |line| stdout_result << line }
29+
stderr.each { |line| stderr_result << line }
30+
end
31+
return [cmd, status, stdout_result, stderr_result]
32+
end
33+
34+
def safe_dscl(*args)
35+
result = dscl(*args)
36+
return "" if ( args.first =~ /^delete/ ) && ( result[1].exitstatus != 0 )
37+
raise(Chef::Exceptions::Group,"dscl error: #{result.inspect}") unless result[1].exitstatus == 0
38+
raise(Chef::Exceptions::Group,"dscl error: #{result.inspect}") if result[2] =~ /No such key: /
39+
return result[2]
40+
end
41+
42+
# This is handled in providers/group.rb by Etc.getgrnam()
43+
# def group_exists?(group)
44+
# groups = safe_dscl("list /Groups")
45+
# !! ( groups =~ Regexp.new("\n#{group}\n") )
46+
# end
47+
48+
# get a free GID greater than 200
49+
def get_free_gid(search_limit=1000)
50+
gid = nil; next_gid_guess = 200
51+
groups_gids = safe_dscl("list /Groups gid")
52+
while(next_gid_guess < search_limit + 200)
53+
if groups_gids =~ Regexp.new("#{next_gid_guess}\n")
54+
next_gid_guess += 1
55+
else
56+
gid = next_gid_guess
57+
break
58+
end
59+
end
60+
return gid || raise("gid not found. Exhausted. Searched #{search_limit} times")
61+
end
62+
63+
def gid_used?(gid)
64+
return false unless gid
65+
groups_gids = safe_dscl("list /Groups gid")
66+
!! ( groups_gids =~ Regexp.new("#{gid}\n") )
67+
end
68+
69+
def set_gid
70+
@new_resource.gid(get_free_gid) if [nil,""].include? @new_resource.gid
71+
raise(Chef::Exceptions::Group,"gid is already in use") if gid_used?(@new_resource.gid)
72+
safe_dscl("create /Groups/#{@new_resource.group_name} PrimaryGroupID #{@new_resource.gid}")
73+
end
74+
75+
def set_members
76+
unless @new_resource.append
77+
Chef::Log.debug("#{@new_resource}: removing group members #{@current_resource.members.join(' ')}") unless @current_resource.members.empty?
78+
safe_dscl("create /Groups/#{@new_resource.group_name} GroupMembers") # clear guid list
79+
safe_dscl("create /Groups/#{@new_resource.group_name} GroupMembership") # clear user list
80+
end
81+
Chef::Log.debug("#{@new_resource}: setting group members #{@new_resource.members.join(', ')}") unless @new_resource.members.empty?
82+
safe_dscl("append /Groups/#{@new_resource.group_name} GroupMembership #{@new_resource.members.join(' ')}")
83+
end
84+
85+
def load_current_resource
86+
super
87+
raise Chef::Exceptions::Group, "Could not find binary /usr/bin/dscl for #{@new_resource}" unless ::File.exists?("/usr/bin/dscl")
88+
end
89+
90+
def create_group
91+
manage_group(false)
92+
end
93+
94+
def manage_group(manage=true)#
95+
fields = []
96+
if manage
97+
[:group_name,:gid,:members].each do |field|
98+
if @current_resource.send(field) != @new_resource.send(field)
99+
fields << field if @new_resource.send(field)
100+
end
101+
end
102+
else
103+
# create
104+
fields = [:group_name,:gid,:members]
105+
end
106+
107+
fields.each do |field|
108+
case field
109+
when :group_name
110+
safe_dscl("create /Groups/#{@new_resource.group_name}")
111+
safe_dscl("create /Groups/#{@new_resource.group_name} Password '*'")
112+
113+
when :gid
114+
set_gid
115+
116+
when :members
117+
set_members
118+
end
119+
end
120+
end
121+
122+
def remove_group
123+
safe_dscl("delete /Groups/#{@new_resource.group_name}")
124+
end
125+
end
126+
end
127+
end
128+
end

0 commit comments

Comments
 (0)