Skip to content

Commit

Permalink
Merge pull request #338 from pcarlisle/ticket/2.7.x/freebsd-user-pass…
Browse files Browse the repository at this point in the history
…words

(#11046) improve freebsd user and group providers
  • Loading branch information
slippycheeze committed Jan 18, 2012
2 parents 8b3e440 + 032043e commit 75d7cad
Show file tree
Hide file tree
Showing 4 changed files with 344 additions and 12 deletions.
34 changes: 24 additions & 10 deletions lib/puppet/provider/group/pw.rb
@@ -1,34 +1,48 @@
require 'puppet/provider/nameservice/pw'

Puppet::Type.type(:group).provide :pw, :parent => Puppet::Provider::NameService::PW do
desc "Group management via `pw`.
desc "Group management via `pw` on FreeBSD."

Only works on FreeBSD.
commands :pw => "pw"
has_features :manages_members

"

commands :pw => "/usr/sbin/pw"
defaultfor :operatingsystem => :freebsd

options :members, :flag => "-M", :method => :mem

verify :gid, "GID must be an integer" do |value|
value.is_a? Integer
end

def addcmd
cmd = [command(:pw), "groupadd", @resource[:name]]

if gid = @resource.should(:gid)
unless gid == :absent
cmd << flag(:gid) << gid
end
end

# Apparently, contrary to the man page, groupadd does
# not accept -o.
#if @parent[:allowdupe] == :true
# cmd << "-o"
#end
if members = @resource.should(:members)
unless members == :absent
if members.is_a?(Array)
members = members.join(",")
end
cmd << "-M" << members
end
end

cmd << "-o" if @resource.allowdupe?

cmd
end

def modifycmd(param, value)
# members may be an array, need a comma separated list
if param == :members and value.is_a?(Array)
value = value.join(",")
end
super(param, value)
end
end

58 changes: 56 additions & 2 deletions lib/puppet/provider/user/pw.rb
@@ -1,16 +1,18 @@
require 'puppet/provider/nameservice/pw'
require 'open3'

Puppet::Type.type(:user).provide :pw, :parent => Puppet::Provider::NameService::PW do
desc "User management via `pw` on FreeBSD."

commands :pw => "pw"
has_features :manages_homedir, :allows_duplicates
has_features :manages_homedir, :allows_duplicates, :manages_passwords, :manages_expiry

defaultfor :operatingsystem => :freebsd

options :home, :flag => "-d", :method => :dir
options :comment, :method => :gecos
options :groups, :flag => "-G"
options :expiry, :method => :expire

verify :gid, "GID must be an integer" do |value|
value.is_a? Integer
Expand All @@ -23,10 +25,14 @@
def addcmd
cmd = [command(:pw), "useradd", @resource[:name]]
@resource.class.validproperties.each do |property|
next if property == :ensure
next if property == :ensure or property == :password
# the value needs to be quoted, mostly because -c might
# have spaces in it
if value = @resource.should(property) and value != ""
if property == :expiry
# FreeBSD uses DD-MM-YYYY rather than YYYY-MM-DD
value = value.split("-").reverse.join("-")
end
cmd << flag(property) << value
end
end
Expand All @@ -37,5 +43,53 @@ def addcmd

cmd
end

def modifycmd(param, value)
if param == :expiry
# FreeBSD uses DD-MM-YYYY rather than YYYY-MM-DD
value = value.split("-").reverse.join("-")
end
cmd = super(param, value)
cmd << "-m" if @resource.managehome?
cmd
end

def create
super

# Set the password after create if given
self.password = @resource[:password] if @resource[:password]
end

# use pw to update password hash
def password=(cryptopw)
Puppet.debug "change password for user '#{@resource[:name]}' method called with hash '#{cryptopw}'"
stdin, stdout, stderr = Open3.popen3("pw user mod #{@resource[:name]} -H 0")
stdin.puts(cryptopw)
stdin.close
Puppet.debug "finished password for user '#{@resource[:name]}' method called with hash '#{cryptopw}'"
end

# get password from /etc/master.passwd
def password
Puppet.debug "checking password for user '#{@resource[:name]}' method called"
current_passline = `getent passwd #{@resource[:name]}`
current_password = current_passline.chomp.split(':')[1] if current_passline
Puppet.debug "finished password for user '#{@resource[:name]}' method called : '#{current_password}'"
current_password
end

# Get expiry from system and convert to Puppet-style date
def expiry
expiry = self.get(:expiry)
expiry = :absent if expiry == 0

if expiry != :absent
t = Time.at(expiry)
expiry = "%4d-%02d-%02d" % [t.year, t.month, t.mday]
end

expiry
end
end

81 changes: 81 additions & 0 deletions spec/unit/provider/group/pw_spec.rb
@@ -0,0 +1,81 @@
#!/usr/bin/env rspec
require 'spec_helper'

provider_class = Puppet::Type.type(:group).provider(:pw)

describe provider_class do
let :resource do
Puppet::Type.type(:group).new(:name => "testgroup", :provider => :pw)
end

let :provider do
resource.provider
end

describe "when creating groups" do
let :provider do
prov = resource.provider
prov.expects(:exists?).returns nil
prov
end

it "should run pw with no additional flags when no properties are given" do
provider.addcmd.must == [provider_class.command(:pw), "groupadd", "testgroup"]
provider.expects(:execute).with([provider_class.command(:pw), "groupadd", "testgroup"])
provider.create
end

it "should use -o when allowdupe is enabled" do
resource[:allowdupe] = true
provider.expects(:execute).with(includes("-o"))
provider.create
end

it "should use -g with the correct argument when the gid property is set" do
resource[:gid] = 12345
provider.expects(:execute).with(all_of(includes("-g"), includes(12345)))
provider.create
end

it "should use -M with the correct argument when the members property is set" do
resource[:members] = "user1"
provider.expects(:execute).with(all_of(includes("-M"), includes("user1")))
provider.create
end

it "should use -M with all the given users when the members property is set to an array" do
resource[:members] = ["user1", "user2"]
provider.expects(:execute).with(all_of(includes("-M"), includes("user1,user2")))
provider.create
end
end

describe "when deleting groups" do
it "should run pw with no additional flags" do
provider.expects(:exists?).returns true
provider.deletecmd.must == [provider_class.command(:pw), "groupdel", "testgroup"]
provider.expects(:execute).with([provider_class.command(:pw), "groupdel", "testgroup"])
provider.delete
end
end

describe "when modifying groups" do
it "should run pw with the correct arguments" do
provider.modifycmd("gid", 12345).must == [provider_class.command(:pw), "groupmod", "testgroup", "-g", 12345]
provider.expects(:execute).with([provider_class.command(:pw), "groupmod", "testgroup", "-g", 12345])
provider.gid = 12345
end

it "should use -M with the correct argument when the members property is changed" do
resource[:members] = "user1"
provider.expects(:execute).with(all_of(includes("-M"), includes("user2")))
provider.members = "user2"
end

it "should use -M with all the given users when the members property is changed with an array" do
resource[:members] = ["user1", "user2"]
provider.expects(:execute).with(all_of(includes("-M"), includes("user3,user4")))
provider.members = ["user3", "user4"]
end
end
end

0 comments on commit 75d7cad

Please sign in to comment.