diff --git a/lib/puppet/provider/user/pw.rb b/lib/puppet/provider/user/pw.rb index 842397971..cdf0e891d 100644 --- a/lib/puppet/provider/user/pw.rb +++ b/lib/puppet/provider/user/pw.rb @@ -1,95 +1,101 @@ 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, :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 end verify :groups, "Groups must be comma-separated" do |value| value !~ /\s/ end def addcmd cmd = [command(:pw), "useradd", @resource[:name]] @resource.class.validproperties.each do |property| 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 cmd << "-o" if @resource.allowdupe? cmd << "-m" if @resource.managehome? 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 deletecmd + cmd = super + cmd << "-r" 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 diff --git a/spec/unit/provider/user/pw_spec.rb b/spec/unit/provider/user/pw_spec.rb index 495fef35b..e90989a00 100755 --- a/spec/unit/provider/user/pw_spec.rb +++ b/spec/unit/provider/user/pw_spec.rb @@ -1,183 +1,202 @@ #!/usr/bin/env rspec require 'spec_helper' provider_class = Puppet::Type.type(:user).provider(:pw) describe provider_class do let :resource do Puppet::Type.type(:user).new(:name => "testuser", :provider => :pw) end describe "when creating users" 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), "useradd", "testuser"] provider.expects(:execute).with([provider_class.command(:pw), "useradd", "testuser"]) 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 -c with the correct argument when the comment property is set" do resource[:comment] = "Testuser Name" provider.expects(:execute).with(all_of(includes("-c"), includes("Testuser Name"))) provider.create end it "should use -e with the correct argument when the expiry property is set" do resource[:expiry] = "2010-02-19" provider.expects(:execute).with(all_of(includes("-e"), includes("19-02-2010"))) 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 -G with the correct argument when the groups property is set" do resource[:groups] = "group1" provider.expects(:execute).with(all_of(includes("-G"), includes("group1"))) provider.create end it "should use -G with all the given groups when the groups property is set to an array" do resource[:groups] = ["group1", "group2"] provider.expects(:execute).with(all_of(includes("-G"), includes("group1,group2"))) provider.create end it "should use -d with the correct argument when the home property is set" do resource[:home] = "/home/testuser" provider.expects(:execute).with(all_of(includes("-d"), includes("/home/testuser"))) provider.create end it "should use -m when the managehome property is enabled" do resource[:managehome] = true provider.expects(:execute).with(includes("-m")) provider.create end it "should call the password set function with the correct argument when the password property is set" do resource[:password] = "*" provider.expects(:execute) provider.expects(:password=).with("*") provider.create end it "should use -s with the correct argument when the shell property is set" do resource[:shell] = "/bin/sh" provider.expects(:execute).with(all_of(includes("-s"), includes("/bin/sh"))) provider.create end it "should use -u with the correct argument when the uid property is set" do resource[:uid] = 12345 provider.expects(:execute).with(all_of(includes("-u"), includes(12345))) provider.create end # (#7500) -p should not be used to set a password (it means something else) it "should not use -p when a password is given" do resource[:password] = "*" provider.addcmd.should_not include("-p") provider.expects(:password=) provider.expects(:execute).with(Not(includes("-p"))) provider.create end end describe "when deleting users" do it "should run pw with no additional flags" do provider = resource.provider provider.expects(:exists?).returns true provider.deletecmd.must == [provider_class.command(:pw), "userdel", "testuser"] provider.expects(:execute).with([provider_class.command(:pw), "userdel", "testuser"]) provider.delete end + + # The above test covers this, but given the consequences of + # accidently deleting a user's home directory it seems better to + # have an explicit test. + it "should not use -r when managehome is not set" do + provider = resource.provider + provider.expects(:exists?).returns true + resource[:managehome] = false + provider.expects(:execute).with(Not(includes("-r"))) + provider.delete + end + + it "should use -r when managehome is set" do + provider = resource.provider + provider.expects(:exists?).returns true + resource[:managehome] = true + provider.expects(:execute).with(includes("-r")) + provider.delete + end end describe "when modifying users" do let :provider do resource.provider end it "should run pw with the correct arguments" do provider.modifycmd("uid", 12345).must == [provider_class.command(:pw), "usermod", "testuser", "-u", 12345] provider.expects(:execute).with([provider_class.command(:pw), "usermod", "testuser", "-u", 12345]) provider.uid = 12345 end it "should use -c with the correct argument when the comment property is changed" do resource[:comment] = "Testuser Name" provider.expects(:execute).with(all_of(includes("-c"), includes("Testuser New Name"))) provider.comment = "Testuser New Name" end it "should use -e with the correct argument when the expiry property is changed" do resource[:expiry] = "2010-02-19" provider.expects(:execute).with(all_of(includes("-e"), includes("19-02-2011"))) provider.expiry = "2011-02-19" end it "should use -g with the correct argument when the gid property is changed" do resource[:gid] = 12345 provider.expects(:execute).with(all_of(includes("-g"), includes(54321))) provider.gid = 54321 end it "should use -G with the correct argument when the groups property is changed" do resource[:groups] = "group1" provider.expects(:execute).with(all_of(includes("-G"), includes("group2"))) provider.groups = "group2" end it "should use -G with all the given groups when the groups property is changed with an array" do resource[:groups] = ["group1", "group2"] provider.expects(:execute).with(all_of(includes("-G"), includes("group3,group4"))) provider.groups = "group3,group4" end it "should use -d with the correct argument when the home property is changed" do resource[:home] = "/home/testuser" provider.expects(:execute).with(all_of(includes("-d"), includes("/newhome/testuser"))) provider.home = "/newhome/testuser" end it "should use -m and -d with the correct argument when the home property is changed and managehome is enabled" do resource[:home] = "/home/testuser" resource[:managehome] = true provider.expects(:execute).with(all_of(includes("-d"), includes("/newhome/testuser"), includes("-m"))) provider.home = "/newhome/testuser" end it "should call the password set function with the correct argument when the password property is changed" do resource[:password] = "*" provider.expects(:password=).with("!") provider.password = "!" end it "should use -s with the correct argument when the shell property is changed" do resource[:shell] = "/bin/sh" provider.expects(:execute).with(all_of(includes("-s"), includes("/bin/tcsh"))) provider.shell = "/bin/tcsh" end it "should use -u with the correct argument when the uid property is changed" do resource[:uid] = 12345 provider.expects(:execute).with(all_of(includes("-u"), includes(54321))) provider.uid = 54321 end end end