[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, experimental, updated. debian/2.6.8-1-844-g7ec39d5

Hector Rivas Gandara keymon at gmail.com
Tue May 10 08:03:52 UTC 2011


The following commit has been merged in the experimental branch:
commit aa8c09fbb0298adb48654a68778e46d9f68f9fb9
Author: Hector Rivas Gandara <keymon at gmail.com>
Date:   Tue Dec 28 14:46:38 2010 +0100

    (#5432) Use AIX native commands to manage users and groups
    
    Specific providers should be created for AIX to manage users and groups.
    
    AIX bases the authentication management on a set of commands: mkuser, rmuser, chuser, lsuser, mkgroup, rmgroup, chgroup, lsg
    
    This commit implements such providers.
    
    The types where extended with:
     - feature: :manages_aix_lam
     - newparam(ia_load_module): authentication module to use in user and group AIX providers.
     - newproperty("attributes"): AIX attributes that are not managed by puppet directely.
    
    Notes::
     - AIX users can have expiry date defined with minute granularity,
       but puppet does not allow it. There is a ticket open for that (#5431)
     - AIX maximum password age is in WEEKs, not days.
    
    Squashed commit of the following:
    
    commit dd9efff227f60dd7d11e33f754870f6344526097
    Author: Hector Rivas Gandara <keymon at gmail.com>
    Date:   Tue Dec 28 14:42:35 2010 +0100
    
        Added new property "attributes" in AIX group provider for AIX attributes
        that are not managed by puppet directely.
    
    commit cd23fff3a3a4963f12c0029d43db3c530a0e4fa3
    Author: Hector Rivas Gandara <keymon at gmail.com>
    Date:   Tue Dec 28 14:33:50 2010 +0100
    
        Converted file from Windows to Unix format
    
    commit c6929e9b557802fe908469ca51339ce249242c94
    Author: Hector Rivas Gandara <keymon at gmail.com>
    Date:   Tue Dec 28 14:32:29 2010 +0100
    
        Added new property "attributes" in AIX user provider for AIX attributes
        that are not managed by puppet directely.
    
    commit d2814dc9d7730635a17a9bdbbc6ef9518f23b39d
    Author: Hector Rivas Gandara <keymon at gmail.com>
    Date:   Tue Dec 28 12:48:07 2010 +0100
    
        Added feature :ia_load_module and new parameter
        (newparam) ia_load_module, to define authentication module to use
        in user and group AIX providers.
    
    commit 95a4e960a93c1b75a4a0053c07fa192bf552d63b
    Author: Hector Rivas Gandara <keymon at gmail.com>
    Date:   Tue Dec 28 12:46:20 2010 +0100
    
        Fixed typo in if sentence

diff --git a/lib/puppet/provider/aixobject.rb b/lib/puppet/provider/aixobject.rb
index d98e36b..dcb3bff 100755
--- a/lib/puppet/provider/aixobject.rb
+++ b/lib/puppet/provider/aixobject.rb
@@ -193,7 +193,7 @@ class Puppet::Provider::AixObject < Puppet::Provider
           info "Empty key in string 'i'?"
           continue
         end
-        key = key_str.downcase.to_sym
+        key = key_str.to_sym
        
         properties = self.load_attribute(key, val, mapping, properties)
       end
@@ -232,13 +232,13 @@ class Puppet::Provider::AixObject < Puppet::Provider
   # For the colon separated list it will:
   #  1. Get keys from first line.
   #  2. Parse next line.
-  def parse_command_output(output)
+  def parse_command_output(output, mapping=self.class.attribute_mapping_from)
     lines = output.split("\n")
     # if it begins with #something:... is a colon separated list.
     if lines[0] =~ /^#.*:/ 
-      self.parse_colon_list(lines[1], lines[0][1..-1].split(':'))
+      self.parse_colon_list(lines[1], lines[0][1..-1].split(':'), mapping)
     else
-      self.parse_attr_list(lines[0])
+      self.parse_attr_list(lines[0], mapping)
     end
   end
 
@@ -247,7 +247,10 @@ class Puppet::Provider::AixObject < Puppet::Provider
     if @objectinfo.nil? or refresh == true
       # Execute lsuser, split all attributes and add them to a dict.
       begin
+        output = execute(self.lscmd)
         @objectinfo = self.parse_command_output(execute(self.lscmd))
+        # All attributtes without translation
+        @objectosinfo = self.parse_command_output(execute(self.lscmd), nil)
       rescue Puppet::ExecutionFailure => detail
         # Print error if needed. FIXME: Do not check the user here.
         Puppet.debug "aix.getinfo(): Could not find #{@resource.class.name} #{@resource.name}: #{detail}" 
@@ -256,6 +259,15 @@ class Puppet::Provider::AixObject < Puppet::Provider
     @objectinfo
   end
 
+  # Retrieve what we can about our object, without translate the values.
+  def getosinfo(refresh = false)
+    if @objectosinfo .nil? or refresh == true
+      getinfo(refresh)
+    end
+    @objectosinfo
+  end
+
+
   # List all elements of given type. It works for colon separated commands and
   # list commands. 
   def list_all
@@ -369,7 +381,7 @@ class Puppet::Provider::AixObject < Puppet::Provider
     @property_hash[symbolize(param)] = value
     
     if getinfo().nil?
-      # This is weird...
+      # This is weird... 
       raise Puppet::Error, "Trying to update parameter '#{param}' to '#{value}' for a resource that does not exists #{@resource.class.name} #{@resource.name}: #{detail}"
     end
     if value == getinfo()[param.to_sym]
@@ -377,7 +389,6 @@ class Puppet::Provider::AixObject < Puppet::Provider
     end
     
     #self.class.validate(param, value)
-    
     if cmd = modifycmd({param =>value})
       begin
         execute(cmd)
diff --git a/lib/puppet/provider/group/aix.rb b/lib/puppet/provider/group/aix.rb
index 6ae16b5..ceb8898 100755
--- a/lib/puppet/provider/group/aix.rb
+++ b/lib/puppet/provider/group/aix.rb
@@ -9,17 +9,12 @@ require 'puppet/provider/aixobject'
 Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject do
   desc "Group management for AIX! Users are managed with mkgroup, rmgroup, lsgroup, chgroup"
 
-  # Constants
-  # Default extra attributes to add when element is created
-  # registry=compat: Needed if you are using LDAP by default.
-  @DEFAULT_EXTRA_ATTRS = [ "registry=compat",  ]
-
-
-  # This will the the default provider for this platform
+    # This will the the default provider for this platform
   defaultfor :operatingsystem => :aix
   confine :operatingsystem => :aix
 
   # Provider features
+  has_features :manages_aix_lam
   has_features :manages_members
 
   # Commands that manage the element
@@ -28,6 +23,11 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
   commands :delete    => "/usr/sbin/rmgroup"
   commands :modify    => "/usr/bin/chgroup"
 
+  # Group attributes to ignore
+  def self.attribute_ignore
+    []
+  end
+
   # AIX attributes to properties mapping.
   # 
   # Valid attributes to be managed by this provider.
@@ -45,8 +45,20 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
   
   #--------------
   # Command lines
+  
+  def get_ia_module_args
+    if @resource[:ia_load_module]
+      ["-R", @resource[:ia_load_module].to_s]
+    else
+      []
+    end
+  end
+  
+  
   def lscmd(value=@resource[:name])
-    [self.class.command(:list), "-R", self.class.ia_module , value]
+    [self.class.command(:list)] +
+      self.get_ia_module_args +
+      [ value]
   end
 
   def lsallcmd()
@@ -58,18 +70,40 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
     # Puppet does not call to self.<parameter>= method if it does not exists.
     #
     # It gets an extra list of arguments to add to the user.
-    [self.class.command(:add), "-R", self.class.ia_module  ]+
+    [self.class.command(:add) ] +
+      self.get_ia_module_args +
       self.hash2args(@resource.to_hash) +
       extra_attrs + [@resource[:name]]
   end
 
-  def modifycmd(hash = property_hash)
-    [self.class.command(:modify), "-R", self.class.ia_module ]+
-      self.hash2args(hash) + [@resource[:name]]
+  def modifycmd(hash = property_hash, translate=true)
+    if translate
+      args = self.hash2args(hash)
+    else 
+      args = self.hash2args(hash, nil)
+    end
+    return nil if args.empty?
+    
+    [self.class.command(:modify)] +
+      self.get_ia_module_args +
+      args + [@resource[:name]]
   end
 
   def deletecmd
-    [self.class.command(:delete),"-R", self.class.ia_module, @resource[:name]]
+    [self.class.command(:delete)] +
+      self.get_ia_module_args +
+      [@resource[:name]]
+  end
+
+
+  def get_arguments(key, value, mapping, objectinfo)
+    # In the case of attributes, return a list of key=vlaue
+    if key == :attributes
+      raise Puppet::Error, "Attributes must be a list of pairs key=value on #{@resource.class.name}[#{@resource.name}]" \
+        unless value and value.is_a? Hash
+      return value.select { |k,v| true }.map { |pair| pair.join("=") }
+    end
+    super(key, value, mapping, objectinfo)
   end
 
   # Force convert users it a list.
@@ -77,4 +111,32 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
     (value.is_a? String) ? value.split(',') : value
   end
 
+  def filter_attributes(hash)
+    # Return only not managed attributtes.
+    hash.select {
+        |k,v| !self.class.attribute_mapping_from.include?(k) and
+                !self.class.attribute_ignore.include?(k)
+      }.inject({}) {
+        |hash, array| hash[array[0]] = array[1]; hash
+      }
+  end
+
+  def attributes
+    filter_attributes(getosinfo(refresh = false))
+  end
+
+  def attributes=(attr_hash)
+    #self.class.validate(param, value)
+    param = :attributes
+    cmd = modifycmd({param => filter_attributes(attr_hash)}, false)
+    if cmd 
+      begin
+        execute(cmd)
+      rescue Puppet::ExecutionFailure  => detail
+        raise Puppet::Error, "Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}"
+      end
+    end
+  end
+
+
 end
diff --git a/lib/puppet/provider/user/aix.rb b/lib/puppet/provider/user/aix.rb
index 06dfd52..c231da8 100755
--- a/lib/puppet/provider/user/aix.rb
+++ b/lib/puppet/provider/user/aix.rb
@@ -1,299 +1,351 @@
-#
-# User Puppet provider for AIX. It uses standar commands to manage users:
-#  mkuser, rmuser, lsuser, chuser
-#
-# Notes:
-# - AIX users can have expiry date defined with minute granularity,
-#   but puppet does not allow it. There is a ticket open for that (#5431)
-# - AIX maximum password age is in WEEKs, not days
-# - I force the compat IA module. 
-#
-# See  http://projects.puppetlabs.com/projects/puppet/wiki/Development_Provider_Development
-# for more information
-#
-# Author::    Hector Rivas Gandara <keymon at gmail.com>
-#
-# TODO::
-#  - Add new AIX specific attributes, specilly registry and SYSTEM.
-#  
-require 'puppet/provider/aixobject'
-require 'tempfile'
-require 'date'
-
-Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do
-  desc "User management for AIX! Users are managed with mkuser, rmuser, chuser, lsuser"
-
-  # Constants
-  # Default extra attributes to add when element is created
-  # registry=compat SYSTEM=compat: Needed if you are using LDAP by default.
-  @DEFAULT_EXTRA_ATTRS = [ "registry=compat", "SYSTEM=compat" ]
-
-  # This will the the default provider for this platform
-  defaultfor :operatingsystem => :aix
-  confine :operatingsystem => :aix
-
-  # Commands that manage the element
-  commands :list      => "/usr/sbin/lsuser"
-  commands :add       => "/usr/bin/mkuser"
-  commands :delete    => "/usr/sbin/rmuser"
-  commands :modify    => "/usr/bin/chuser"
-  
-  commands :lsgroup   => "/usr/sbin/lsgroup"
-  commands :chpasswd  => "/bin/chpasswd"
-
-  # Provider features
-  has_features :manages_homedir, :manages_passwords
-  has_features :manages_expiry,  :manages_password_age
-
-  # Attribute verification (TODO)
-  #verify :gid, "GID must be an string or int of a valid group" do |value|
-  #  value.is_a? String || value.is_a? Integer
-  #end
-  #
-  #verify :groups, "Groups must be comma-separated" do |value|
-  #  value !~ /\s/
-  #end
-
-  # AIX attributes to properties mapping.
-  # 
-  # Valid attributes to be managed by this provider.
-  # It is a list with of hash
-  #  :aix_attr      AIX command attribute name
-  #  :puppet_prop   Puppet propertie name
-  #  :to            Method to adapt puppet property to aix command value. Optional.
-  #  :from            Method to adapt aix command value to puppet property. Optional
-  self.attribute_mapping = [
-    #:name => :name,
-    {:aix_attr => :pgrp,     :puppet_prop => :gid,
-        :to => :gid_to_attr, :from => :gid_from_attr},
-    {:aix_attr => :id,       :puppet_prop => :uid},
-    {:aix_attr => :groups,   :puppet_prop => :groups},
-    {:aix_attr => :home,     :puppet_prop => :home},
-    {:aix_attr => :shell,    :puppet_prop => :shell},
-    {:aix_attr => :expires,  :puppet_prop => :expiry,
-        :to => :expiry_to_attr, :from => :expiry_from_attr},
-    {:aix_attr => :maxage,   :puppet_prop => :password_max_age},
-    {:aix_attr => :minage,   :puppet_prop => :password_min_age},
-  ]
-  
-  #--------------
-  # Command lines
-  
-  def lsgroupscmd(value=@resource[:name])
-    [command(:lsgroup),"-R", self.class.ia_module, "-a", "id", value]
-  end
-
-  def lscmd(value=@resource[:name])
-    [self.class.command(:list), "-R", self.class.ia_module , value]
-  end
-
-  def lsallcmd()
-    lscmd("ALL")
-  end
-
-  def addcmd(extra_attrs = [])
-    # Here we use the @resource.to_hash to get the list of provided parameters
-    # Puppet does not call to self.<parameter>= method if it does not exists.
-    #
-    # It gets an extra list of arguments to add to the user.
-    [self.class.command(:add), "-R", self.class.ia_module  ]+
-      self.hash2args(@resource.to_hash) +
-      extra_attrs + [@resource[:name]]
-  end
-
-  def modifycmd(hash = property_hash)
-    [self.class.command(:modify), "-R", self.class.ia_module ]+
-      self.hash2args(hash) + [@resource[:name]]
-  end
-
-  def deletecmd
-    [self.class.command(:delete),"-R", self.class.ia_module, @resource[:name]]
-  end
-
-  #--------------
-  # We overwrite the create function to change the password after creation.
-  def create
-    super
-    # Reset the password if needed
-    self.password = @resource[:password] if @resource[:password]
-  end 
-
-  
-  # Get the groupname from its id
-  def self.groupname_by_id(gid)
-    groupname=nil
-    execute(lsgroupscmd("ALL")).each { |entry|
-      attrs = self.parse_attr_list(entry, nil)
-      if attrs and attrs.include? :id and gid == attrs[:id].to_i
-        groupname = entry.split(" ")[0]
-      end
-    }
-    groupname
-  end
-
-  # Get the groupname from its id
-  def groupid_by_name(groupname)
-    attrs = self.parse_attr_list(execute(lsgroupscmd(groupname)).split("\n")[0], nil)
-    attrs ? attrs[:id].to_i : nil
-  end
-
-  # Check that a group exists and is valid
-  def verify_group(value)
-    if value.is_a? Integer or value.is_a? Fixnum  
-      groupname = self.groupname_by_id(value)
-      raise ArgumentError, "AIX group must be a valid existing group" unless groupname
-    else 
-      raise ArgumentError, "AIX group must be a valid existing group" unless groupid_by_name(value)
-      groupname = value
-    end
-    groupname
-  end
-  
-  # The user's primary group.  Can be specified numerically or by name.
-  def gid_to_attr(value)
-    verify_group(value)
-  end
-
-  def gid_from_attr(value)
-    groupid_by_name(value)
-  end
-
-  # The expiry date for this user. Must be provided in
-  # a zero padded YYYY-MM-DD HH:MM format 
-  def expiry_to_attr(value)
-    # For chuser the expires parameter is a 10-character string in the MMDDhhmmyy format
-    # that is,"%m%d%H%M%y"
-    newdate = '0'
-    if value.is_a? String and value!="0000-00-00"
-      d = DateTime.parse(value, "%Y-%m-%d %H:%M")
-      newdate = d.strftime("%m%d%H%M%y")
-    end
-    newdate
-  end
-  
-  def expiry_from_attr(value)
-    if value =~ /(..)(..)(..)(..)(..)/
-      #d= DateTime.parse("20#{$5}-#{$1}-#{$2} #{$3}:#{$4}")
-      #expiry_date = d.strftime("%Y-%m-%d %H:%M")
-      #expiry_date = d.strftime("%Y-%m-%d")
-      expiry_date = "20#{$5}-#{$1}-#{$2}"
-    else
-      Puppet.warn("Could not convert AIX expires date '#{value}' on #{@resource.class.name}[#{@resource.name}]") \
-        unless value == '0'
-      expiry_date = :absent
-    end
-    expiry_date
-  end
-
-  #--------------------------------
-  # Getter and Setter
-  # When the provider is initialized, create getter/setter methods for each
-  # property our resource type supports.
-  # If setter or getter already defined it will not be overwritten
-
-  #- **password**
-  #    The user's password, in whatever encrypted format the local machine
-  #    requires. Be sure to enclose any value that includes a dollar sign ($)
-  #    in single quotes (').  Requires features manages_passwords.
-  #
-  # Retrieve the password parsing directly the /etc/security/passwd
-  def password
-    password = :absent
-    user = @resource[:name]
-    f = File.open("/etc/security/passwd", 'r')
-    # Skip to the user
-    f.each { |l| break if l  =~ /^#{user}:\s*$/ }
-    if ! f.eof?
-      f.each { |l|
-        # If there is a new user stanza, stop
-        break if l  =~ /^\S*:\s*$/ 
-        # If the password= entry is found, return it
-        if l  =~ /^\s*password\s*=\s*(.*)$/
-          password = $1; break;
-        end
-      }
-    end
-    f.close()
-    return password
-  end 
-
-  def password=(value)
-    user = @resource[:name]
-    
-    # Puppet execute does not support strings as input, only files.
-    tmpfile = Tempfile.new('puppet_#{user}_pw')
-    tmpfile << "#{user}:#{value}\n"
-    tmpfile.close()
-
-    # Options '-e', '-c', use encrypted password and clear flags
-    # Must receibe "user:enc_password" as input
-    # command, arguments = {:failonfail => true, :combine => true}
-    cmd = [self.class.command(:chpasswd),"-R", self.class.ia_module,
-           '-e', '-c', user]
-    begin
-      execute(cmd, {:failonfail => true, :combine => true, :stdinfile => tmpfile.path })
-    rescue Puppet::ExecutionFailure  => detail
-      raise Puppet::Error, "Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}"
-    ensure
-      tmpfile.delete()
-    end
-  end 
-
-  #- **comment**
-  #    A description of the user.  Generally is a user's full name.
-  #def comment=(value)
-  #end
-  #
-  #def comment
-  #end
-  # UNSUPPORTED
-  #- **profile_membership**
-  #    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.  Valid values are
-  #    `inclusive`, `minimum`.
-  # UNSUPPORTED
-  #- **profiles**
-  #    The profiles the user has.  Multiple profiles should be
-  #    specified as an array.  Requires features manages_solaris_rbac.
-  # UNSUPPORTED
-  #- **project**
-  #    The name of the project associated with a user  Requires features
-  #    manages_solaris_rbac.
-  # UNSUPPORTED
-  #- **role_membership**
-  #    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.  Valid values are
-  #    `inclusive`, `minimum`.
-  # UNSUPPORTED
-  #- **roles**
-  #    The roles the user has.  Multiple roles should be
-  #    specified as an array.  Requires features manages_solaris_rbac.
-  # UNSUPPORTED
-  #- **key_membership**
-  #    Whether specified key value pairs should be treated as the only
-  #    attributes
-  #    of the user or whether they should merely
-  #    be treated as the minimum list.  Valid values are `inclusive`,
-  #    `minimum`.
-  # UNSUPPORTED
-  #- **keys**
-  #    Specify user attributes in an array of keyvalue pairs  Requires features
-  #    manages_solaris_rbac.
-  # UNSUPPORTED
-  #- **allowdupe**
-  #  Whether to allow duplicate UIDs.  Valid values are `true`, `false`.
-  # UNSUPPORTED
-  #- **auths**
-  #    The auths the user has.  Multiple auths should be
-  #    specified as an array.  Requires features manages_solaris_rbac.
-  # UNSUPPORTED
-  #- **auth_membership**
-  #    Whether specified auths should be treated as the only auths
-  #    of which the user is a member or whether they should merely
-  #    be treated as the minimum membership list.  Valid values are
-  #    `inclusive`, `minimum`.
-  # UNSUPPORTED
-
-end
+#
+# User Puppet provider for AIX. It uses standar commands to manage users:
+#  mkuser, rmuser, lsuser, chuser
+#
+# Notes:
+# - AIX users can have expiry date defined with minute granularity,
+#   but puppet does not allow it. There is a ticket open for that (#5431)
+# - AIX maximum password age is in WEEKs, not days
+# - I force the compat IA module. 
+#
+# See  http://projects.puppetlabs.com/projects/puppet/wiki/Development_Provider_Development
+# for more information
+#
+# Author::    Hector Rivas Gandara <keymon at gmail.com>
+#
+require 'puppet/provider/aixobject'
+require 'tempfile'
+require 'date'
+
+Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do
+  desc "User management for AIX! Users are managed with mkuser, rmuser, chuser, lsuser"
+
+  # This will the the default provider for this platform
+  defaultfor :operatingsystem => :aix
+  confine :operatingsystem => :aix
+
+  # Commands that manage the element
+  commands :list      => "/usr/sbin/lsuser"
+  commands :add       => "/usr/bin/mkuser"
+  commands :delete    => "/usr/sbin/rmuser"
+  commands :modify    => "/usr/bin/chuser"
+  
+  commands :lsgroup   => "/usr/sbin/lsgroup"
+  commands :chpasswd  => "/bin/chpasswd"
+
+  # Provider features
+  has_features :manages_aix_lam
+  has_features :manages_homedir, :manages_passwords
+  has_features :manages_expiry,  :manages_password_age
+
+  # Attribute verification (TODO)
+  #verify :gid, "GID must be an string or int of a valid group" do |value|
+  #  value.is_a? String || value.is_a? Integer
+  #end
+  #
+  #verify :groups, "Groups must be comma-separated" do |value|
+  #  value !~ /\s/
+  #end
+
+  # User attributes to ignore
+  def self.attribute_ignore
+    []
+  end
+
+  # AIX attributes to properties mapping.
+  # 
+  # Valid attributes to be managed by this provider.
+  # It is a list with of hash
+  #  :aix_attr      AIX command attribute name
+  #  :puppet_prop   Puppet propertie name
+  #  :to            Method to adapt puppet property to aix command value. Optional.
+  #  :from            Method to adapt aix command value to puppet property. Optional
+  self.attribute_mapping = [
+    #:name => :name,
+    {:aix_attr => :pgrp,     :puppet_prop => :gid,
+        :to => :gid_to_attr, :from => :gid_from_attr},
+    {:aix_attr => :id,       :puppet_prop => :uid},
+    {:aix_attr => :groups,   :puppet_prop => :groups},
+    {:aix_attr => :home,     :puppet_prop => :home},
+    {:aix_attr => :shell,    :puppet_prop => :shell},
+    {:aix_attr => :expires,  :puppet_prop => :expiry,
+        :to => :expiry_to_attr, :from => :expiry_from_attr},
+    {:aix_attr => :maxage,   :puppet_prop => :password_max_age},
+    {:aix_attr => :minage,   :puppet_prop => :password_min_age},
+  ]
+  
+  #--------------
+  # Command lines
+  def get_ia_module_args
+    if @resource[:ia_load_module]
+      ["-R", @resource[:ia_load_module].to_s]
+    else
+      []
+    end
+  end
+  
+  def lsgroupscmd(value=@resource[:name])
+    [command(:lsgroup)] +
+      self.get_ia_module_args +
+      ["-a", "id", value]
+  end
+
+  def lscmd(value=@resource[:name])
+    [self.class.command(:list)] + self.get_ia_module_args + [ value]
+  end
+
+  def lsallcmd()
+    lscmd("ALL")
+  end
+
+  def addcmd(extra_attrs = [])
+    # Here we use the @resource.to_hash to get the list of provided parameters
+    # Puppet does not call to self.<parameter>= method if it does not exists.
+    #
+    # It gets an extra list of arguments to add to the user.
+    [self.class.command(:add)] + self.get_ia_module_args +
+      self.hash2args(@resource.to_hash) +
+      extra_attrs + [@resource[:name]]
+  end
+
+  # Get modify command
+  def modifycmd(hash = property_hash, translate=true)
+    if translate
+      args = self.hash2args(hash)
+    else 
+      args = self.hash2args(hash, nil)
+    end
+    return nil if args.empty?
+    
+    [self.class.command(:modify)] + self.get_ia_module_args +
+      args + [@resource[:name]]
+  end
+
+  def deletecmd
+    [self.class.command(:delete)] + self.get_ia_module_args + [@resource[:name]]
+  end
+
+  #--------------
+  # We overwrite the create function to change the password after creation.
+  def create
+    super
+    # Reset the password if needed
+    self.password = @resource[:password] if @resource[:password]
+  end 
+
+  
+  def get_arguments(key, value, mapping, objectinfo)
+    # In the case of attributes, return a list of key=vlaue
+    if key == :attributes
+      raise Puppet::Error, "Attributes must be a list of pairs key=value on #{@resource.class.name}[#{@resource.name}]" \
+        unless value and value.is_a? Hash
+      return value.select { |k,v| true }.map { |pair| pair.join("=") }
+    end
+    super(key, value, mapping, objectinfo)
+  end
+  
+  # Get the groupname from its id
+  def self.groupname_by_id(gid)
+    groupname=nil
+    execute(lsgroupscmd("ALL")).each { |entry|
+      attrs = self.parse_attr_list(entry, nil)
+      if attrs and attrs.include? :id and gid == attrs[:id].to_i
+        groupname = entry.split(" ")[0]
+      end
+    }
+    groupname
+  end
+
+  # Get the groupname from its id
+  def groupid_by_name(groupname)
+    attrs = self.parse_attr_list(execute(lsgroupscmd(groupname)).split("\n")[0], nil)
+    attrs ? attrs[:id].to_i : nil
+  end
+
+  # Check that a group exists and is valid
+  def verify_group(value)
+    if value.is_a? Integer or value.is_a? Fixnum  
+      groupname = self.groupname_by_id(value)
+      raise ArgumentError, "AIX group must be a valid existing group" unless groupname
+    else 
+      raise ArgumentError, "AIX group must be a valid existing group" unless groupid_by_name(value)
+      groupname = value
+    end
+    groupname
+  end
+  
+  # The user's primary group.  Can be specified numerically or by name.
+  def gid_to_attr(value)
+    verify_group(value)
+  end
+
+  def gid_from_attr(value)
+    groupid_by_name(value)
+  end
+
+  # The expiry date for this user. Must be provided in
+  # a zero padded YYYY-MM-DD HH:MM format 
+  def expiry_to_attr(value)
+    # For chuser the expires parameter is a 10-character string in the MMDDhhmmyy format
+    # that is,"%m%d%H%M%y"
+    newdate = '0'
+    if value.is_a? String and value!="0000-00-00"
+      d = DateTime.parse(value, "%Y-%m-%d %H:%M")
+      newdate = d.strftime("%m%d%H%M%y")
+    end
+    newdate
+  end
+  
+  def expiry_from_attr(value)
+    if value =~ /(..)(..)(..)(..)(..)/
+      #d= DateTime.parse("20#{$5}-#{$1}-#{$2} #{$3}:#{$4}")
+      #expiry_date = d.strftime("%Y-%m-%d %H:%M")
+      #expiry_date = d.strftime("%Y-%m-%d")
+      expiry_date = "20#{$5}-#{$1}-#{$2}"
+    else
+      Puppet.warn("Could not convert AIX expires date '#{value}' on #{@resource.class.name}[#{@resource.name}]") \
+        unless value == '0'
+      expiry_date = :absent
+    end
+    expiry_date
+  end
+
+  #--------------------------------
+  # Getter and Setter
+  # When the provider is initialized, create getter/setter methods for each
+  # property our resource type supports.
+  # If setter or getter already defined it will not be overwritten
+
+  #- **password**
+  #    The user's password, in whatever encrypted format the local machine
+  #    requires. Be sure to enclose any value that includes a dollar sign ($)
+  #    in single quotes (').  Requires features manages_passwords.
+  #
+  # Retrieve the password parsing directly the /etc/security/passwd
+  def password
+    password = :absent
+    user = @resource[:name]
+    f = File.open("/etc/security/passwd", 'r')
+    # Skip to the user
+    f.each { |l| break if l  =~ /^#{user}:\s*$/ }
+    if ! f.eof?
+      f.each { |l|
+        # If there is a new user stanza, stop
+        break if l  =~ /^\S*:\s*$/ 
+        # If the password= entry is found, return it
+        if l  =~ /^\s*password\s*=\s*(.*)$/
+          password = $1; break;
+        end
+      }
+    end
+    f.close()
+    return password
+  end 
+
+  def password=(value)
+    user = @resource[:name]
+    
+    # Puppet execute does not support strings as input, only files.
+    tmpfile = Tempfile.new('puppet_#{user}_pw')
+    tmpfile << "#{user}:#{value}\n"
+    tmpfile.close()
+
+    # Options '-e', '-c', use encrypted password and clear flags
+    # Must receibe "user:enc_password" as input
+    # command, arguments = {:failonfail => true, :combine => true}
+    cmd = [self.class.command(:chpasswd),"-R", self.class.ia_module,
+           '-e', '-c', user]
+    begin
+      execute(cmd, {:failonfail => true, :combine => true, :stdinfile => tmpfile.path })
+    rescue Puppet::ExecutionFailure  => detail
+      raise Puppet::Error, "Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}"
+    ensure
+      tmpfile.delete()
+    end
+  end 
+
+  def filter_attributes(hash)
+    # Return only not managed attributtes.
+    hash.select {
+        |k,v| !self.class.attribute_mapping_from.include?(k) and
+                !self.class.attribute_ignore.include?(k)
+      }.inject({}) {
+        |hash, array| hash[array[0]] = array[1]; hash
+      }
+  end
+
+  def attributes
+    filter_attributes(getosinfo(refresh = false))
+  end
+
+  def attributes=(attr_hash)
+    #self.class.validate(param, value)
+    param = :attributes
+    cmd = modifycmd({param => filter_attributes(attr_hash)}, false)
+    if cmd 
+      begin
+        execute(cmd)
+      rescue Puppet::ExecutionFailure  => detail
+        raise Puppet::Error, "Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}"
+      end
+    end
+  end
+
+  #- **comment**
+  #    A description of the user.  Generally is a user's full name.
+  #def comment=(value)
+  #end
+  #
+  #def comment
+  #end
+  # UNSUPPORTED
+  #- **profile_membership**
+  #    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.  Valid values are
+  #    `inclusive`, `minimum`.
+  # UNSUPPORTED
+  #- **profiles**
+  #    The profiles the user has.  Multiple profiles should be
+  #    specified as an array.  Requires features manages_solaris_rbac.
+  # UNSUPPORTED
+  #- **project**
+  #    The name of the project associated with a user  Requires features
+  #    manages_solaris_rbac.
+  # UNSUPPORTED
+  #- **role_membership**
+  #    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.  Valid values are
+  #    `inclusive`, `minimum`.
+  # UNSUPPORTED
+  #- **roles**
+  #    The roles the user has.  Multiple roles should be
+  #    specified as an array.  Requires features manages_solaris_rbac.
+  # UNSUPPORTED
+  #- **key_membership**
+  #    Whether specified key value pairs should be treated as the only
+  #    attributes
+  #    of the user or whether they should merely
+  #    be treated as the minimum list.  Valid values are `inclusive`,
+  #    `minimum`.
+  # UNSUPPORTED
+  #- **keys**
+  #    Specify user attributes in an array of keyvalue pairs  Requires features
+  #    manages_solaris_rbac.
+  # UNSUPPORTED
+  #- **allowdupe**
+  #  Whether to allow duplicate UIDs.  Valid values are `true`, `false`.
+  # UNSUPPORTED
+  #- **auths**
+  #    The auths the user has.  Multiple auths should be
+  #    specified as an array.  Requires features manages_solaris_rbac.
+  # UNSUPPORTED
+  #- **auth_membership**
+  #    Whether specified auths should be treated as the only auths
+  #    of which the user is a member or whether they should merely
+  #    be treated as the minimum membership list.  Valid values are
+  #    `inclusive`, `minimum`.
+  # UNSUPPORTED
+
+end
diff --git a/lib/puppet/type/group.rb b/lib/puppet/type/group.rb
index cde1cfd..aa96bd9 100755
--- a/lib/puppet/type/group.rb
+++ b/lib/puppet/type/group.rb
@@ -15,6 +15,9 @@ module Puppet
     feature :manages_members,
       "For directories where membership is an attribute of groups not users."
 
+    feature :manages_aix_lam,
+      "The provider can manage AIX Loadable Authentication Module (LAM) system."
+
     ensurable do
       desc "Create or remove the group."
 
@@ -95,5 +98,38 @@ module Puppet
 
       defaultto false
     end
+
+    newparam(:ia_load_module, :required_features => :manages_aix_lam) do
+      desc "The name of the I&A module to use to manage this user"
+
+      defaultto "compat"
+    end
+
+    newproperty(:attributes, :parent => Puppet::Property::KeyValue, :required_features => :manages_aix_lam) do
+      desc "Specify group AIX attributes in an array of keyvalue pairs"
+
+      def membership
+        :attribute_membership
+      end
+      
+      def delimiter
+        " "
+      end
+
+      validate do |value|
+        raise ArgumentError, "Attributes value pairs must be seperated by an =" unless value.include?("=")
+      end
+    end
+
+    newparam(:attribute_membership) do
+      desc "Whether specified attribute value pairs should be treated as the only attributes
+        of the user or whether they should merely
+        be treated as the minimum list."
+
+      newvalues(:inclusive, :minimum)
+
+      defaultto :minimum
+    end
+
   end
 end
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index 761d5d7..b2cafad 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -34,6 +34,9 @@ module Puppet
     feature :manages_expiry,
       "The provider can manage the expiry date for a user."
 
+    feature :manages_aix_lam,
+      "The provider can manage AIX Loadable Authentication Module (LAM) system."
+
     newproperty(:ensure, :parent => Puppet::Property::Ensure) do
       newvalue(:present, :event => :user_created) do
         provider.create
@@ -434,5 +437,39 @@ module Puppet
     newproperty(:project, :required_features => :manages_solaris_rbac) do
       desc "The name of the project associated with a user"
     end
+
+    newparam(:ia_load_module, :required_features => :manages_aix_lam) do
+      desc "The name of the I&A module to use to manage this user"
+
+      defaultto "compat"
+    end
+
+    newproperty(:attributes, :parent => Puppet::Property::KeyValue, :required_features => :manages_aix_lam) do
+      desc "Specify user AIX attributes in an array of keyvalue pairs"
+
+      def membership
+        :attribute_membership
+      end
+      
+      def delimiter
+        " "
+      end
+
+      validate do |value|
+        raise ArgumentError, "Attributes value pairs must be seperated by an =" unless value.include?("=")
+      end
+    end
+
+    newparam(:attribute_membership) do
+      desc "Whether specified attribute value pairs should be treated as the only attributes
+        of the user or whether they should merely
+        be treated as the minimum list."
+
+      newvalues(:inclusive, :minimum)
+      
+      defaultto :minimum
+    end
+
+
   end
 end

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list