diff options
author | Adam Jacob <adam@hjksolutions.com> | 2008-10-05 18:22:15 -0700 |
---|---|---|
committer | Adam Jacob <adam@hjksolutions.com> | 2008-10-05 18:22:15 -0700 |
commit | ba2b16491fe376357c5c0dd3ffb902aef66bf698 (patch) | |
tree | 7e5e91633e14bfc1a6e397690f334e0eebe29a6d | |
parent | ac33143e3ff45c2c98ec2265d2b4fc1bb4b429f1 (diff) | |
download | chef-ba2b16491fe376357c5c0dd3ffb902aef66bf698.tar.gz |
Adding user provider
-rw-r--r-- | lib/chef/exceptions.rb | 2 | ||||
-rw-r--r-- | lib/chef/platform.rb | 3 | ||||
-rw-r--r-- | lib/chef/provider/user.rb | 163 | ||||
-rw-r--r-- | lib/chef/provider/user/useradd.rb | 74 | ||||
-rw-r--r-- | lib/chef/resource/user.rb | 96 |
5 files changed, 337 insertions, 1 deletions
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb index a70692b001..fa037a7f6c 100644 --- a/lib/chef/exceptions.rb +++ b/lib/chef/exceptions.rb @@ -24,5 +24,7 @@ class Chef class SearchIndex < RuntimeError; end class Override < RuntimeError; end class UnsupportedAction < RuntimeError; end + class MissingLibrary < RuntimeError; end + class User < RuntimeError; end end end diff --git a/lib/chef/platform.rb b/lib/chef/platform.rb index 57332bc6ab..56d26f6c5d 100644 --- a/lib/chef/platform.rb +++ b/lib/chef/platform.rb @@ -53,7 +53,8 @@ class Chef :python => Chef::Provider::Script, :ruby => Chef::Provider::Script, :bash => Chef::Provider::Script, - :csh => Chef::Provider::Script + :csh => Chef::Provider::Script, + :user => Chef::Provider::User::Useradd, } } diff --git a/lib/chef/provider/user.rb b/lib/chef/provider/user.rb new file mode 100644 index 0000000000..15f96e72fc --- /dev/null +++ b/lib/chef/provider/user.rb @@ -0,0 +1,163 @@ +# +# Author:: Adam Jacob (<adam@hjksolutions.com>) +# Copyright:: Copyright (c) 2008 HJK Solutions, LLC +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require File.join(File.dirname(__FILE__), "..", "mixin", "command") +require 'etc' + +class Chef + class Provider + class User < Chef::Provider + + include Chef::Mixin::Command + + def initialize(node, new_resource) + super(node, new_resource) + @user_exists = true + @locked = nil + end + + def load_current_resource + @current_resource = Chef::Resource::User.new(@new_resource.name) + @current_resource.username = @new_resource.username + + user_info = nil + begin + user_info = Etc.getpwnam(@new_resource.username) + rescue ArgumentError => e + @user_exists = false + Chef::Log.debug("User #{@new_resource.username} does not exist") + end + + if user_info + @current_resource.uid(user_info.uid) + @current_resource.gid(user_info.gid) + @current_resource.comment(user_info.gecos) + @current_resource.home(user_info.dir) + @current_resource.shell(user_info.shell) + + if @new_resource.password + begin + require 'shadow' + rescue Exception => e + Chef::Log.error("You must have ruby-shadow installed for password support!") + raise Chef::Exception::MissingLibrary, "You must have ruby-shadow installed for password support!" + end + shadow_info = Shadow::Passwd.getspnam(@new_resource.username) + @current_resource.password(shadow_info.sp_pwdp) + end + end + + @current_resource + end + + def compare_user + change_required = false + change_required = true if @new_resource.uid != @current_resource.uid + change_required = true if @new_resource.gid != @current_resource.gid + change_required = true if @new_resource.comment != @current_resource.comment + change_required = true if @new_resource.home != @current_resource.home + change_required = true if @new_resource.shell != @current_resource.shell + change_required = true if @new_resource.password != @current_resource.password + change_required + end + + def action_create + case @user_exists + when false + create_user + Chef::Log.info("Created #{@new_resource}") + @new_resource.updated(true) + else + if compare_user + manage_user + Chef::Log.info("Altered #{@new_resource}") + @new_resource.updated(true) + end + end + end + + def action_remove + if @user_exists + remove_user + @new_resource.updated(true) + Chef::Log.info("Removed #{@new_resource}") + end + end + + def action_manage + if @user_exists && compare_user + manage_user + @new_resource.updated(true) + Chef::Log.info("Managed #{@new_resource}") + end + end + + def action_modify + if @user_exists && compare_user + manage_user + @new_resource.updated(true) + Chef::Log.info("Modified #{@new_resource}") + else + raise Chef::Exception::User, "Cannot modify #{@new_resource} - user does not exist!" + end + end + + def check_lock + status = popen4("passwd -S #{@new_resource.username}") do |pid, stdin, stdout, stderr| + stdin.close + status_line = stdout.gets.split(' ') + case status_line[1] + when /^P/ + @locked = false + when /^N/ + @locked = false + when /^L/ + @locked = true + end + end + + unless status.exitstatus == 0 + raise Chef::Exception::User, "Cannot determine if #{@new_resource} is locked!" + end + + @locked + end + + def action_lock + if @user_exists && check_lock == false + lock_user + @new_resource.updated(true) + Chef::Log.info("Locked #{@new_resource}") + else + raise Chef::Exception::User, "Cannot lock #{@new_resource} - user does not exist!" + end + end + + def action_unlock + if @user_exists && check_lock = true + unlock_user + @new_resource.updated(true) + Chef::Log.info("Unlocked #{@new_resource}") + else + raise Chef::Exception::User, "Cannot unlock #{@new_resource} - user does not exist!" + end + end + + end + end +end diff --git a/lib/chef/provider/user/useradd.rb b/lib/chef/provider/user/useradd.rb new file mode 100644 index 0000000000..7daf9ac530 --- /dev/null +++ b/lib/chef/provider/user/useradd.rb @@ -0,0 +1,74 @@ +# +# Author:: Adam Jacob (<adam@hjksolutions.com>) +# Copyright:: Copyright (c) 2008 HJK Solutions, LLC +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require File.join(File.dirname(__FILE__), "..", "mixin", "command") +require 'etc' + +class Chef + class Provider + class User + class Useradd < Chef::Provider::User + def create_user + command = "useradd" + command << set_options + run_command(command) + end + + def manage_user + command = "usermod" + command << set_options + run_command(command) + end + + def remove_user + command = "userdel" + command << " -r" if @new_resource.supports[:manage_home] + command << " #{@new_resource.username}" + end + + def lock_user + run_command("usermod -L #{@new_resource.username}") + end + + def unlock_user + run_command("usermod -U #{@new_resource.username}") + end + + def set_options + opts << " -c '#{@new_resource.comment}'" if @new_resource.comment + opts << " -d '#{@new_resource.home}'" if @new_resource.home + opts << " -g '#{@new_resource.gid}'" if @new_resource.gid + opts << " -u '#{@new_resource.uid}'" if @new_resource.uid + opts << " -s '#{@new_resource.shell}'" if @new_resource.shell + opts << " -p '#{@new_resource.password}'" if @new_resource.password + if @new_resource.supports[:manage_home] + case @node[:operatingsystem] + when "Fedora","RedHat","CentOS" + opts << " -M" + else + opts << " -m" + end + end + opts << " #{@new_resource.username}" + opts + end + + end + end + end +end
\ No newline at end of file diff --git a/lib/chef/resource/user.rb b/lib/chef/resource/user.rb new file mode 100644 index 0000000000..1702753408 --- /dev/null +++ b/lib/chef/resource/user.rb @@ -0,0 +1,96 @@ +# +# Author:: Adam Jacob (<adam@hjksolutions.com>) +# Copyright:: Copyright (c) 2008 HJK Solutions, LLC +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +class Chef + class Resource + class User < Chef::Resource + + def initialize(name, collection=nil, node=nil) + super(name, collection, node) + @resource_name = :user + @username = name + @comment = nil + @uid = nil + @gid = nil + @home = nil + @shell = nil + @password = nil + @action = :create + @supports = { :manage_home => false } + @allowed_actions.push(:create, :remove, :modify, :manage, :lock, :unlock) + end + + def username(arg=nil) + set_or_return( + :username, + arg, + :kind_of => [ String ] + ) + end + + def comment(arg=nil) + set_or_return( + :comment, + arg, + :kind_of => [ String ] + ) + end + + def uid(arg=nil) + set_or_return( + :uid, + arg, + :kind_of => [ String, Integer ] + ) + end + + def gid(arg=nil) + set_or_return( + :gid, + arg, + :kind_of => [ String, Integer ] + ) + end + + def home(arg=nil) + set_or_return( + :home, + arg, + :kind_of => [ String ] + ) + end + + def shell(arg=nil) + set_or_return( + :shell, + arg, + :kind_of => [ String ] + ) + end + + def password(arg=nil) + set_or_return( + :password, + arg, + :kind_of => [ String ] + ) + end + + end + end +end
\ No newline at end of file |