[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, master, updated. debian/0.24.6-1-356-g5718585
Andrew Shafer
andrew at reductivelabs.com
Fri Jan 23 14:21:09 UTC 2009
The following commit has been merged in the master branch:
commit d1abb86565b63f98d8fc1395a78c840c45e47238
Author: Andrew Shafer <andrew at reductivelabs.com>
Date: Wed Oct 1 18:58:09 2008 -0600
Add role support to user type and an implemention
modify user type:
add ensure = role logic
add roles property
add manages_solaris_rbac feature
refactored 'list' property to reuse logic for groups in roles
diff --git a/lib/puppet/property/list.rb b/lib/puppet/property/list.rb
new file mode 100644
index 0000000..4e7f6ec
--- /dev/null
+++ b/lib/puppet/property/list.rb
@@ -0,0 +1,78 @@
+require 'puppet/property'
+
+module Puppet
+ class Property
+ class List < Property
+
+ def should_to_s(should_value)
+ #just return the should value
+ should_value
+ end
+
+ def is_to_s(currentvalue)
+ currentvalue.join(delimiter)
+ end
+
+ def membership
+ :membership
+ end
+
+ def add_should_with_current(should, current)
+ if current.is_a?(Array)
+ should += current
+ end
+ should.uniq
+ end
+
+ def inclusive?
+ @resource[membership] == :inclusive
+ end
+
+ def should
+ unless defined? @should and @should
+ return nil
+ end
+
+ members = @should
+ #inclusive means we are managing everything so if it isn't in should, its gone
+ if ! inclusive?
+ members = add_should_with_current(members, retrieve)
+ end
+
+ members.sort.join(delimiter)
+ end
+
+ def delimiter
+ ","
+ end
+
+ def retrieve
+ #ok, some 'convention' if the list property is named groups, provider should implement a groups method
+ if tmp = provider.send(name) and tmp != :absent
+ return tmp.split(delimiter)
+ else
+ return :absent
+ end
+ end
+
+ def prepare_is_for_comparison(is)
+ if is.is_a? Array
+ is = is.sort.join(delimiter)
+ end
+ is
+ end
+
+ def insync?(is)
+ unless defined? @should and @should
+ return true
+ end
+
+ unless is
+ return true
+ end
+
+ return (prepare_is_for_comparison(is) == self.should)
+ end
+ end
+ end
+end
diff --git a/lib/puppet/provider/user/user_role_add.rb b/lib/puppet/provider/user/user_role_add.rb
new file mode 100644
index 0000000..23581ab
--- /dev/null
+++ b/lib/puppet/provider/user/user_role_add.rb
@@ -0,0 +1,89 @@
+require 'puppet/util/user_attr'
+
+Puppet::Type.type(:user).provide :user_role_add, :parent => Puppet::Type::User::ProviderUseradd do
+
+ desc "User management inherits ``useradd`` and adds logic to manage roles on Solaris using roleadd."
+
+ defaultfor :operatingsystem => :solaris
+
+ commands :add => "useradd", :delete => "userdel", :modify => "usermod", :role_add => "roleadd", :role_delete => "roledel", :role_modify => "rolemod"
+ options :home, :flag => "-d", :method => :dir
+ options :comment, :method => :gecos
+ options :groups, :flag => "-G"
+ options :roles, :flag => "-R"
+
+ 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
+
+ has_features :manages_homedir, :allows_duplicates, :manages_solaris_rbac
+
+ if Puppet.features.libshadow?
+ has_feature :manages_passwords
+ end
+
+ def user_attributes
+ @user_attributes ||= UserAttr.get_attributes_by_name(@resource[:name])
+ end
+
+ def flush
+ @user_attributes = nil
+ end
+
+ def command(cmd)
+ if is_role? or (!exists? and @resource[:ensure] == :role)
+ cmd = ("role_" + cmd.to_s).intern
+ end
+ super(cmd)
+ end
+
+ def is_role?
+ user_attributes and user_attributes[:type] == "role"
+ end
+
+ def run(cmd, msg)
+ begin
+ execute(cmd)
+ rescue Puppet::ExecutionFailure => detail
+ raise Puppet::Error, "Could not %s %s %s: %s" %
+ [msg, @resource.class.name, @resource.name, detail]
+ end
+ end
+
+ def transition(type)
+ cmd = [command(:modify)]
+ cmd << "-K" << "type=#{type}"
+ cmd << @resource[:name]
+ end
+
+ def create
+ if is_role?
+ run(transition("normal"), "transition role to")
+ else
+ run(addcmd, "create")
+ end
+ end
+
+ def destroy
+ run(deletecmd, "delete "+ (is_role? ? "role" : "user"))
+ end
+
+ def create_role
+ if exists? and !is_role?
+ run(transition("role"), "transition user to")
+ else
+ run(addcmd, "create role")
+ end
+ end
+
+ def roles
+ if user_attributes
+ user_attributes[:roles]
+ end
+ end
+end
+
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index bb0a86f..74c4c6a 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -1,5 +1,6 @@
require 'etc'
require 'facter'
+require 'puppet/property/list'
module Puppet
newtype(:user) do
@@ -21,6 +22,9 @@ module Puppet
"The provider can modify user passwords, by accepting a password
hash."
+ feature :manages_solaris_rbac,
+ "The provider can manage roles and normal users"
+
newproperty(:ensure, :parent => Puppet::Property::Ensure) do
newvalue(:present, :event => :user_created) do
provider.create
@@ -30,6 +34,10 @@ module Puppet
provider.delete
end
+ newvalue(:role, :event => :role_created, :required_features => :manages_solaris_rbac) do
+ provider.create_role
+ end
+
desc "The basic state that the object should be in."
# If they're talking about the thing at all, they generally want to
@@ -44,7 +52,11 @@ module Puppet
def retrieve
if provider.exists?
- return :present
+ if provider.respond_to?(:is_role?) and provider.is_role?
+ return :role
+ else
+ return :present
+ end
else
return :absent
end
@@ -125,68 +137,36 @@ module Puppet
end
end
- newproperty(:groups) do
+ newproperty(:groups, :parent => Puppet::Property::List) do
desc "The groups of which the user is a member. The primary
group should not be listed. Multiple groups should be
specified as an array."
- def should_to_s(newvalue)
- self.should
- end
-
- def is_to_s(currentvalue)
- currentvalue.join(",")
- end
-
- # We need to override this because the groups need to
- # be joined with commas
- def should
- current_value = retrieve
-
- unless defined? @should and @should
- return nil
- end
-
- if @resource[:membership] == :inclusive
- return @should.sort.join(",")
- else
- members = @should
- if current_value.is_a?(Array)
- members += current_value
- end
- return members.uniq.sort.join(",")
+ validate do |value|
+ if value =~ /^\d+$/
+ raise ArgumentError, "Group names must be provided, not numbers"
end
- end
-
- def retrieve
- if tmp = provider.groups and tmp != :absent
- return tmp.split(",")
- else
- return :absent
+ if value.include?(",")
+ puts value
+ raise ArgumentError, "Group names must be provided as an array, not a comma-separated list"
end
end
+ end
- def insync?(is)
- unless defined? @should and @should
- return true
- end
- unless defined? is and is
- return true
- end
- tmp = is
- if is.is_a? Array
- tmp = is.sort.join(",")
- end
+ newproperty(:roles, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
+ desc "The roles of which the user the user has. The roles should be
+ specified as an array."
- return tmp == self.should
+ def membership
+ :role_membership
end
validate do |value|
if value =~ /^\d+$/
- raise ArgumentError, "Group names must be provided, not numbers"
+ raise ArgumentError, "Role names must be provided, not numbers"
end
if value.include?(",")
- raise ArgumentError, "Group names must be provided as an array, not a comma-separated list"
+ raise ArgumentError, "Role names must be provided as an array, not a comma-separated list"
end
end
end
@@ -202,7 +182,17 @@ module Puppet
desc "Whether specified groups should be treated as the only groups
of which the user is a member or whether they should merely
be treated as the minimum membership list."
-
+
+ newvalues(:inclusive, :minimum)
+
+ defaultto :minimum
+ end
+
+ newparam(:role_membership) do
+ desc "Whether specified roles should be treated as the only roles
+ of which the user is a member or whether they should merely
+ be treated as the minimum membership list."
+
newvalues(:inclusive, :minimum)
defaultto :minimum
diff --git a/spec/unit/property/list.rb b/spec/unit/property/list.rb
new file mode 100644
index 0000000..9c832c0
--- /dev/null
+++ b/spec/unit/property/list.rb
@@ -0,0 +1,147 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/spec_helper.rb") }
+
+require 'puppet/property/list'
+
+list_class = Puppet::Property::List
+
+describe list_class do
+
+ it "should be a subclass of Property" do
+ list_class.superclass.must == Puppet::Property
+ end
+
+ describe "as an instance" do
+ before do
+ # Wow that's a messy interface to the resource.
+ list_class.initvars
+ @resource = stub 'resource', :[]= => nil, :property => nil
+ @property = list_class.new(:resource => @resource)
+ end
+
+ it "should have a , as default delimiter" do
+ @property.delimiter.should == ","
+ end
+
+ it "should have a :membership as default membership" do
+ @property.membership.should == :membership
+ end
+
+ it "should return the same value passed into should_to_s" do
+ @property.should_to_s("foo") == "foo"
+ end
+
+ it "should return the passed in array values joined with the delimiter from is_to_s" do
+ @property.is_to_s(["foo","bar"]).should == "foo,bar"
+ end
+
+ describe "when adding should to current" do
+ it "should add the arrays when current is an array" do
+ @property.add_should_with_current(["foo"], ["bar"]).should == ["foo", "bar"]
+ end
+
+ it "should return should if current is not a array" do
+ @property.add_should_with_current(["foo"], :absent).should == ["foo"]
+ end
+
+ it "should return only the uniq elements" do
+ @property.add_should_with_current(["foo", "bar"], ["foo", "baz"]).should == ["foo", "bar", "baz"]
+ end
+ end
+
+ describe "when calling inclusive?" do
+ it "should use the membership method to look up on the @resource" do
+ @property.expects(:membership).returns(:membership)
+ @resource.expects(:[]).with(:membership)
+ @property.inclusive?
+ end
+
+ it "should return true when @resource[membership] == inclusive" do
+ @property.stubs(:membership).returns(:membership)
+ @resource.stubs(:[]).with(:membership).returns(:inclusive)
+ @property.inclusive?.must == true
+ end
+
+ it "should return false when @resource[membership] != inclusive" do
+ @property.stubs(:membership).returns(:membership)
+ @resource.stubs(:[]).with(:membership).returns(:minimum)
+ @property.inclusive?.must == false
+ end
+ end
+
+ describe "when calling should" do
+ it "should return nil if @should is nil" do
+ @property.should.must == nil
+ end
+
+ it "should return the sorted values of @should as a string if inclusive" do
+ @property.should = ["foo", "bar"]
+ @property.expects(:inclusive?).returns(true)
+ @property.should.must == "bar,foo"
+ end
+
+ it "should return the uniq sorted values of @should + retrieve as a string if !inclusive" do
+ @property.should = ["foo", "bar"]
+ @property.expects(:inclusive?).returns(false)
+ @property.expects(:retrieve).returns(["foo","baz"])
+ @property.should.must == "bar,baz,foo"
+ end
+ end
+
+ describe "when calling retrieve" do
+ before do
+ @provider = mock("provider")
+ @property.stubs(:provider).returns(@provider)
+ end
+
+ it "should send 'name' to the provider" do
+ @provider.expects(:send).with(:group)
+ @property.expects(:name).returns(:group)
+ @property.retrieve
+ end
+
+ it "should return an array with the provider returned info" do
+ @provider.stubs(:send).with(:group).returns("foo,bar,baz")
+ @property.stubs(:name).returns(:group)
+ @property.retrieve == ["foo", "bar", "baz"]
+ end
+
+ it "should return :absent when the provider returns :absent" do
+ @provider.stubs(:send).with(:group).returns(:absent)
+ @property.stubs(:name).returns(:group)
+ @property.retrieve == :absent
+ end
+ end
+
+ describe "when calling insync?" do
+ it "should return true unless @should is defined and not nil" do
+ @property.insync?("foo") == true
+ end
+
+ it "should return true unless the passed in values is not nil" do
+ @property.should = "foo"
+ @property.insync?(nil) == true
+ end
+
+ it "should call prepare_is_for_comparison with value passed in and should" do
+ @property.should = "foo"
+ @property.expects(:prepare_is_for_comparison).with("bar")
+ @property.expects(:should)
+ @property.insync?("bar")
+ end
+
+ it "should return true if prepared value == should value" do
+ @property.should = "bar,foo"
+ @property.expects(:inclusive?).returns(true)
+ @property.insync?(["bar","foo"]).must == true
+ end
+
+ it "should return false if prepared value != should value" do
+ @property.should = "bar,baz,foo"
+ @property.expects(:inclusive?).returns(true)
+ @property.insync?(["bar","foo"]).must == false
+ end
+ end
+ end
+end
diff --git a/spec/unit/provider/user/user_role_add.rb b/spec/unit/provider/user/user_role_add.rb
new file mode 100644
index 0000000..87ad920
--- /dev/null
+++ b/spec/unit/provider/user/user_role_add.rb
@@ -0,0 +1,131 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+provider_class = Puppet::Type.type(:user).provider(:user_role_add)
+
+describe provider_class do
+ before do
+ @resource = stub("resource", :name => "myuser", :managehome? => nil)
+ @resource.stubs(:should).returns "fakeval"
+ @resource.stubs(:[]).returns "fakeval"
+ @resource.stubs(:allowdupe?).returns false
+ @provider = provider_class.new(@resource)
+ end
+
+ describe "when calling command" do
+ before do
+ klass = stub("provider")
+ klass.stubs(:command).with(:foo).returns("userfoo")
+ klass.stubs(:command).with(:role_foo).returns("rolefoo")
+ @provider.stubs(:class).returns(klass)
+ end
+
+ it "should use the command if not a role and ensure!=role" do
+ @provider.stubs(:is_role?).returns(false)
+ @provider.stubs(:exists?).returns(false)
+ @resource.stubs(:[]).with(:ensure).returns(:present)
+ @provider.command(:foo).should == "userfoo"
+ end
+
+ it "should use the role command when a role" do
+ @provider.stubs(:is_role?).returns(true)
+ @provider.command(:foo).should == "rolefoo"
+ end
+
+ it "should use the role command when !exists and ensure=role" do
+ @provider.stubs(:is_role?).returns(false)
+ @provider.stubs(:exists?).returns(false)
+ @resource.stubs(:[]).with(:ensure).returns(:role)
+ @provider.command(:foo).should == "rolefoo"
+ end
+ end
+
+ describe "when calling transition" do
+ it "should return foomod setting the type to bar" do
+ @provider.expects(:command).with(:modify).returns("foomod")
+ @provider.transition("bar").should == ["foomod", "-K", "type=bar", "fakeval"]
+ end
+ end
+
+ describe "when calling create" do
+ it "should use the add command when the user doesn't exist" do
+ @provider.stubs(:exists?).returns(false)
+ @provider.expects(:addcmd).returns("useradd")
+ @provider.expects(:run)
+ @provider.create
+ end
+
+ it "should use transition(normal) when the user is a role" do
+ @provider.stubs(:exists?).returns(true)
+ @provider.stubs(:is_role?).returns(true)
+ @provider.expects(:transition).with("normal")
+ @provider.expects(:run)
+ @provider.create
+ end
+ end
+
+ describe "when calling destroy" do
+ it "should use the delete command if the user exists and is not a role" do
+ @provider.stubs(:exists?).returns(true)
+ @provider.stubs(:is_role?).returns(false)
+ @provider.expects(:deletecmd)
+ @provider.expects(:run)
+ @provider.destroy
+ end
+
+ it "should use the delete command if the user is a role" do
+ @provider.stubs(:exists?).returns(true)
+ @provider.stubs(:is_role?).returns(true)
+ @provider.expects(:deletecmd)
+ @provider.expects(:run)
+ @provider.destroy
+ end
+ end
+
+ describe "when calling create_role" do
+ it "should use the transition(role) if the user exists" do
+ @provider.stubs(:exists?).returns(true)
+ @provider.stubs(:is_role?).returns(false)
+ @provider.expects(:transition).with("role")
+ @provider.expects(:run)
+ @provider.create_role
+ end
+
+ it "should use the add command when role doesn't exists" do
+ @provider.stubs(:exists?).returns(false)
+ @provider.expects(:addcmd)
+ @provider.expects(:run)
+ @provider.create_role
+ end
+ end
+
+ describe "when allow duplicate is enabled" do
+ before do
+ @resource.expects(:allowdupe?).returns true
+ @provider.expects(:execute).with { |args| args.include?("-o") }
+ end
+
+ it "should add -o when the user is being created" do
+ @provider.create
+ end
+
+ it "should add -o when the uid is being modified" do
+ @provider.uid = 150
+ end
+ end
+
+ describe "when getting roles" do
+ it "should get the user_attributes" do
+ @provider.expects(:user_attributes)
+ @provider.roles
+ end
+
+ it "should get the :roles attribute" do
+ attributes = mock("attributes")
+ attributes.expects(:[]).with(:roles)
+ @provider.stubs(:user_attributes).returns(attributes)
+ @provider.roles
+ end
+ end
+end
--
Puppet packaging for Debian
More information about the Pkg-puppet-devel
mailing list