summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Edwards <adamed@opscode.com>2014-09-05 02:48:03 -0700
committerAdam Edwards <adamed@opscode.com>2014-09-05 02:48:03 -0700
commit4e0ccbe8d8e84c3ff229b53fe2b43327b09ee892 (patch)
treebba2a3cc874ec12d64230343ec48d3802ddf6530
parent72b90db4808e770c7cb882cd3eb8b689afccd4dd (diff)
parent526955fbf897f75d23e13836ba5634b7752e787e (diff)
downloadchef-4e0ccbe8d8e84c3ff229b53fe2b43327b09ee892.tar.gz
Merge pull request #1996 from opscode/adamedx/port-chef-1982-11
Port Chef 1982 DSCL provider
-rw-r--r--CHANGELOG.md2
-rw-r--r--lib/chef/provider/user/dscl.rb60
-rw-r--r--spec/unit/provider/user/dscl_spec.rb3
3 files changed, 35 insertions, 30 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1e5272df37..e73e091e25 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,8 @@
# Chef Client Changelog
-
## Unreleased: 11.16.0
+* Fix a bug in user dscl provider to enable managing password and other properties at the same time.
* Add `dsc_script` resource to Chef for PowerShell DSC support on Windows
## Last Release: 11.14.6:
diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb
index 4d1cca21fa..89ffa04ef8 100644
--- a/lib/chef/provider/user/dscl.rb
+++ b/lib/chef/provider/user/dscl.rb
@@ -110,18 +110,18 @@ user password using shadow hash.")
@current_resource = Chef::Resource::User.new(@new_resource.username)
@current_resource.username(@new_resource.username)
- user_info = read_user_info
- if user_info
- @current_resource.uid(dscl_get(user_info, :uid))
- @current_resource.gid(dscl_get(user_info, :gid))
- @current_resource.home(dscl_get(user_info, :home))
- @current_resource.shell(dscl_get(user_info, :shell))
- @current_resource.comment(dscl_get(user_info, :comment))
- @authentication_authority = dscl_get(user_info, :auth_authority)
-
- if @new_resource.password && dscl_get(user_info, :password) == "********"
+ @user_info = read_user_info
+ if @user_info
+ @current_resource.uid(dscl_get(@user_info, :uid))
+ @current_resource.gid(dscl_get(@user_info, :gid))
+ @current_resource.home(dscl_get(@user_info, :home))
+ @current_resource.shell(dscl_get(@user_info, :shell))
+ @current_resource.comment(dscl_get(@user_info, :comment))
+ @authentication_authority = dscl_get(@user_info, :auth_authority)
+
+ if @new_resource.password && dscl_get(@user_info, :password) == "********"
# A password is set. Let's get the password information from shadow file
- shadow_hash_binary = dscl_get(user_info, :shadow_hash)
+ shadow_hash_binary = dscl_get(@user_info, :shadow_hash)
# Calling shell_out directly since we want to give an input stream
shadow_hash_xml = convert_binary_plist_to_xml(shadow_hash_binary.string)
@@ -158,22 +158,26 @@ user password using shadow hash.")
def create_user
dscl_create_user
+ # set_password modifies the plist file of the user directly. So update
+ # the password first before making any modifications to the user.
+ set_password
dscl_create_comment
dscl_set_uid
dscl_set_gid
dscl_set_home
dscl_set_shell
- set_password
end
def manage_user
+ # set_password modifies the plist file of the user directly. So update
+ # the password first before making any modifications to the user.
+ set_password if diverged_password?
dscl_create_user if diverged?(:username)
dscl_create_comment if diverged?(:comment)
dscl_set_uid if diverged?(:uid)
dscl_set_gid if diverged?(:gid)
dscl_set_home if diverged?(:home)
dscl_set_shell if diverged?(:shell)
- set_password if diverged_password?
end
#
@@ -339,22 +343,18 @@ user password using shadow hash.")
:input => shadow_info.to_plist, :live_stream => shadow_info_binary)
command.run_command
+ if @user_info.nil?
+ # User is just created. read_user_info() will read the fresh information
+ # for the user with a cache flush. However with experimentation we've seen
+ # that dscl cache is not immediately updated after the creation of the user
+ # This is odd and needs to be investigated further.
+ sleep 3
+ @user_info = read_user_info
+ end
+
# Replace the shadow info in user's plist
- user_info = read_user_info
- dscl_set(user_info, :shadow_hash, shadow_info_binary)
-
- #
- # Before saving the user's plist file we need to wait for dscl to
- # update its caches and flush them to disk. In order to achieve this
- # we need to wait first for our changes to get into the dscl cache
- # and then flush the cache to disk before saving password into the
- # plist file. 3 seconds is the minimum experimental value for dscl
- # cache to be updated. We can get rid of this sleep when we find a
- # trigger to update dscl cache.
- #
- sleep 3
- shell_out("dscacheutil '-flushcache'")
- save_user_info(user_info)
+ dscl_set(@user_info, :shadow_hash, shadow_info_binary)
+ save_user_info(@user_info)
end
#
@@ -555,6 +555,10 @@ user password using shadow hash.")
def read_user_info
user_info = nil
+ # We flush the cache here in order to make sure that we read fresh information
+ # for the user.
+ shell_out("dscacheutil '-flushcache'")
+
begin
user_plist_file = "#{USER_PLIST_DIRECTORY}/#{@new_resource.username}.plist"
user_plist_info = run_plutil("convert xml1 -o - #{user_plist_file}")
diff --git a/spec/unit/provider/user/dscl_spec.rb b/spec/unit/provider/user/dscl_spec.rb
index 3cb18f1979..b272eceada 100644
--- a/spec/unit/provider/user/dscl_spec.rb
+++ b/spec/unit/provider/user/dscl_spec.rb
@@ -376,6 +376,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
let(:user_plist_file) { nil }
before do
+ provider.should_receive(:shell_out).with("dscacheutil '-flushcache'")
provider.should_receive(:shell_out).with("plutil -convert xml1 -o - /var/db/dslocal/nodes/Default/users/toor.plist") do
if user_plist_file.nil?
ShellCmdResult.new('Can not find the file', 'Sorry!!', 1)
@@ -715,7 +716,6 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
provider.should_receive(:read_user_info)
provider.should_receive(:dscl_set)
provider.should_receive(:sleep).with(3)
- provider.should_receive(:shell_out).with("dscacheutil '-flushcache'")
provider.should_receive(:save_user_info)
provider.set_password
end
@@ -822,6 +822,7 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30")
describe "when the user exists" do
before do
+ provider.should_receive(:shell_out).with("dscacheutil '-flushcache'")
provider.should_receive(:shell_out).with("plutil -convert xml1 -o - /var/db/dslocal/nodes/Default/users/toor.plist") do
ShellCmdResult.new(File.read(File.join(CHEF_SPEC_DATA, "mac_users/10.9.plist.xml")), "", 0)
end