diff --git a/lib/puppet/provider/aixobject.rb b/lib/puppet/provider/aixobject.rb index dcb3bff78..9506c67a2 100755 --- a/lib/puppet/provider/aixobject.rb +++ b/lib/puppet/provider/aixobject.rb @@ -1,411 +1,393 @@ # -# Common code for AIX providers -# +# Common code for AIX providers. This class implements basic structure for +# AIX resources. # Author:: Hector Rivas Gandara # -# class Puppet::Provider::AixObject < Puppet::Provider - desc "User management for AIX! Users are managed with mkuser, rmuser, chuser, lsuser" - - # Constants - # Loadable AIX I/A module for users and groups. By default we manage compat. - # TODO:: add a type parameter to change this - class << self - attr_accessor :ia_module - end + desc "Generic AIX resource provider" # The real provider must implement these functions. def lscmd(value=@resource[:name]) raise Puppet::Error, "Method not defined #{@resource.class.name} #{@resource.name}: #{detail}" end def lscmd(value=@resource[:name]) raise Puppet::Error, "Method not defined #{@resource.class.name} #{@resource.name}: #{detail}" end def addcmd(extra_attrs = []) raise Puppet::Error, "Method not defined #{@resource.class.name} #{@resource.name}: #{detail}" end def modifycmd(attributes_hash) raise Puppet::Error, "Method not defined #{@resource.class.name} #{@resource.name}: #{detail}" end def deletecmd raise Puppet::Error, "Method not defined #{@resource.class.name} #{@resource.name}: #{detail}" end - # Valid attributes to be managed by this provider. # It is a list of hashes # :aix_attr AIX command attribute name # :puppet_prop Puppet propertie name # :to Optional. Method name that adapts puppet property to aix command value. # :from Optional. Method to adapt aix command line value to puppet property. Optional class << self attr_accessor :attribute_mapping end + + # Mapping from Puppet property to AIX attribute. def self.attribute_mapping_to if ! @attribute_mapping_to @attribute_mapping_to = {} attribute_mapping.each { |elem| attribute_mapping_to[elem[:puppet_prop]] = { :key => elem[:aix_attr], :method => elem[:to] } } end @attribute_mapping_to end + + # Mapping from AIX attribute to Puppet property. def self.attribute_mapping_from if ! @attribute_mapping_from @attribute_mapping_from = {} attribute_mapping.each { |elem| attribute_mapping_from[elem[:aix_attr]] = { :key => elem[:puppet_prop], :method => elem[:from] } } end @attribute_mapping_from end # This functions translates a key and value using the given mapping. # Mapping can be nil (no translation) or a hash with this format # {:key => new_key, :method => translate_method} - # It returns a list [key, value] + # It returns a list with the pair [key, value] def translate_attr(key, value, mapping) return [key, value] unless mapping return nil unless mapping[key] if mapping[key][:method] new_value = method(mapping[key][:method]).call(value) else new_value = value end [mapping[key][:key], new_value] end - - # Gets the given command line argument for the given key, value and mapping. - def get_arg(key, value, mapping) - arg = nil - if ret = self.translate_attr(key, val, mapping) - new_key = ret[0] - new_val = ret[1] - - # Arrays are separated by commas - if new_val.is_a? Array - value = new_val.join(",") - else - value = new_val.to_s - end - - # Get the needed argument - if mapping[key][:to_arg] - arg = method(mapping[key][:to_arg]).call(new_key, value) - else - arg = (new_key.to_s + "=" + value ) - end - end - return arg - end - - # Reads and attribute. - # Here we implement the default behaviour. - # Subclasses must reimplement this. + # Loads an AIX attribute (key=value) and stores it in the given hash with + # puppet semantics. It translates the pair using the given mapping. + # + # This operation works with each property one by one, + # subclasses must reimplement this if more complex operations are needed def load_attribute(key, value, mapping, objectinfo) if mapping.nil? objectinfo[key] = value elsif mapping[key].nil? # is not present in mapping, ignore it. true elsif mapping[key][:method].nil? objectinfo[mapping[key][:key]] = value elsif objectinfo[mapping[key][:key]] = method(mapping[key][:method]).call(value) end return objectinfo end + # Gets the given command line argument for the given key and value, + # using the given mapping to translate key and value. + # All the objectinfo hash (@resource or @property_hash) is passed. + # + # This operation works with each property one by one, + # and default behaviour is return the arguments as key=value pairs. + # Subclasses must reimplement this if more complex operations/arguments + # are needed + # def get_arguments(key, value, mapping, objectinfo) if mapping.nil? new_key = key new_value = value elsif mapping[key].nil? # is not present in mapping, ignore it. new_key = nil new_value = nil elsif mapping[key][:method].nil? new_key = mapping[key][:key] new_value = value elsif new_key = mapping[key][:key] new_value = method(mapping[key][:method]).call(value) end # convert it to string - if new_value.is_a? Array - new_value = new_value.join(",") - else - new_value = new_value.to_s - end + new_value = Array(new_value).join(',') if new_key return [ "#{new_key}=#{new_value}" ] else return [] end end - # Convert the provider properties to AIX command arguments (string) - # This function will translate each value/key and generate the argument. - # By default, arguments are created as aix_key=aix_value + # Convert the provider properties (hash) to AIX command arguments + # (list of strings) + # This function will translate each value/key and generate the argument using + # the get_arguments function. def hash2args(hash, mapping=self.class.attribute_mapping_to) return "" unless hash arg_list = [] hash.each {|key, val| arg_list += self.get_arguments(key, val, mapping, hash) } arg_list end - # Parse AIX command attributes in a format of space separated of key=value - # pairs: "uid=100 groups=a,b,c" - # It returns and return provider hash. + # Parse AIX command attributes from the output of an AIX command, that + # which format is a list of space separated of key=value pairs: + # "uid=100 groups=a,b,c". + # It returns an hash. # # If a mapping is provided, the keys are translated as defined in the - # mapping hash. Only values included in mapping will be added + # mapping hash. And only values included in mapping will be added + # # NOTE: it will ignore the items not including '=' def parse_attr_list(str, mapping=self.class.attribute_mapping_from) properties = {} attrs = [] if !str or (attrs = str.split()).empty? return nil end attrs.each { |i| if i.include? "=" # Ignore if it does not include '=' (key_str, val) = i.split('=') # Check the key if !key_str or key_str.empty? info "Empty key in string 'i'?" continue end key = key_str.to_sym properties = self.load_attribute(key, val, mapping, properties) end } properties.empty? ? nil : properties end - # Parse AIX colon separated list of attributes, using given list of keys - # to name the attributes. This function is useful to parse the output - # of commands like lsfs -c: + # Parse AIX command output in a colon separated list of attributes, + # This function is useful to parse the output of commands like lsfs -c: # #MountPoint:Device:Vfs:Nodename:Type:Size:Options:AutoMount:Acct # /:/dev/hd4:jfs2::bootfs:557056:rw:yes:no # /home:/dev/hd1:jfs2:::2129920:rw:yes:no # /usr:/dev/hd2:jfs2::bootfs:9797632:rw:yes:no # # If a mapping is provided, the keys are translated as defined in the - # mapping hash. Only values included in mapping will be added - # NOTE: it will ignore the items not including '=' + # mapping hash. And only values included in mapping will be added def parse_colon_list(str, key_list, mapping=self.class.attribute_mapping_from) properties = {} attrs = [] if !str or (attrs = str.split(':')).empty? return nil end attrs.each { |val| key = key_list.shift.downcase.to_sym properties = self.load_attribute(key, val, mapping, properties) } properties.empty? ? nil : properties end - # Default parsing function for colon separated list or attributte list - # (key=val pairs). It will choose the method depending of the first line. + # Default parsing function for AIX commands. + # It will choose the method depending of the first line. # For the colon separated list it will: # 1. Get keys from first line. # 2. Parse next line. 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(':'), mapping) else self.parse_attr_list(lines[0], mapping) end end - # Retrieve what we can about our object + # Retrieve all the information of an existing resource. + # It will execute 'lscmd' command and parse the output, using the mapping + # 'attribute_mapping_from' to translate the keys and values. def getinfo(refresh = false) 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}" end end @objectinfo end - # Retrieve what we can about our object, without translate the values. + # Like getinfo, but it will not use the mapping to translate the keys and values. + # It might be usefult to retrieve some raw information. 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. + # list commands. + # It returns a list of names. def list_all names = [] begin output = execute(self.lsallcmd()).split('\n') (output.select{ |l| l != /^#/ }).each { |v| name = v.split(/[ :]/) names << name if not name.empty? } rescue Puppet::ExecutionFailure => detail # Print error if needed Puppet.debug "aix.list_all(): Could not get all resources of type #{@resource.class.name}: #{detail}" end names end #------------- # Provider API # ------------ # Clear out the cached values. def flush @property_hash.clear if @property_hash @objectinfo.clear if @objectinfo end # Check that the user exists def exists? !!getinfo(true) # !! => converts to bool end + # Return all existing instances + # The method for returning a list of provider instances. Note that it returns + # providers, preferably with values already filled in, not resources. + def self.instances + objects=[] + self.list_all().each { |entry| + objects << new(:name => entry, :ensure => :present) + } + objects + end + #- **ensure** # The basic state that the object should be in. Valid values are # `present`, `absent`, `role`. # From ensurable: exists?, create, delete def ensure if exists? :present else :absent end end - # Return all existing instances - # The method for returning a list of provider instances. Note that it returns - # providers, preferably with values already filled in, not resources. - def self.instances - objects=[] - self.list_all().each { |entry| - objects << new(:name => entry, :ensure => :present) - } - objects - end - + # Create a new instance of the resource def create if exists? info "already exists" # The object already exists return nil end begin execute(self.addcmd) rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not create #{@resource.class.name} #{@resource.name}: #{detail}" end end + # Delete this instance of the resource def delete unless exists? info "already absent" # the object already doesn't exist return nil end begin execute(self.deletecmd) rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not delete #{@resource.class.name} #{@resource.name}: #{detail}" end end #-------------------------------- - # Call this method when the object is initialized, - # create getter/setter methods for each property our resource type supports. + # Call this method when the object is initialized. + # It creates getter/setter methods for each property our resource type supports. # If setter or getter already defined it will not be overwritten def self.mk_resource_methods [resource_type.validproperties, resource_type.parameters].flatten.each do |prop| next if prop == :ensure define_method(prop) { get(prop) || :absent} unless public_method_defined?(prop) define_method(prop.to_s + "=") { |*vals| set(prop, *vals) } unless public_method_defined?(prop.to_s + "=") end end - # - + # Define the needed getters and setters as soon as we know the resource type def self.resource_type=(resource_type) super mk_resource_methods end # Retrieve a specific value by name. def get(param) (hash = getinfo(false)) ? hash[param] : nil end # Set a property. def set(param, value) @property_hash[symbolize(param)] = value if getinfo().nil? # 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] return end #self.class.validate(param, value) if cmd = modifycmd({param =>value}) begin execute(cmd) rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Could not set #{param} on #{@resource.class.name}[#{@resource.name}]: #{detail}" end end # Refresh de info. hash = getinfo(true) end def initialize(resource) super @objectinfo = nil - # FIXME: Initiallize this properly. - self.class.ia_module="compat" + @objectosinfo = nil end end diff --git a/lib/puppet/provider/group/aix.rb b/lib/puppet/provider/group/aix.rb index ceb889840..ecdef6070 100755 --- a/lib/puppet/provider/group/aix.rb +++ b/lib/puppet/provider/group/aix.rb @@ -1,142 +1,141 @@ # # Group Puppet provider for AIX. It uses standard commands to manage groups: # mkgroup, rmgroup, lsgroup, chgroup # # Author:: Hector Rivas Gandara # 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" - # 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 commands :list => "/usr/sbin/lsgroup" commands :add => "/usr/bin/mkgroup" 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. # 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 + # :from Method to adapt aix command value to puppet property. Optional self.attribute_mapping = [ #:name => :name, {:aix_attr => :id, :puppet_prop => :gid }, {:aix_attr => :users, :puppet_prop => :members, :from => :users_from_attr}, + {:aix_attr => :attributes, :puppet_prop => :attributes}, ] #-------------- - # Command lines + # Command definition + # Return the IA module arguments based on the resource param ia_load_module 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)] + 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.= 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 - def modifycmd(hash = property_hash, translate=true) - if translate - args = self.hash2args(hash) - else - args = self.hash2args(hash, nil) - end + def modifycmd(hash = property_hash) + args = self.hash2args(hash) 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 + #-------------- + # Overwrite get_arguments to add the attributes arguments 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. - def users_from_attr(value) - (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) + cmd = modifycmd({param => filter_attributes(attr_hash)}) 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 + # Force convert users it a list. + def users_from_attr(value) + (value.is_a? String) ? value.split(',') : value + end + end diff --git a/lib/puppet/provider/user/aix.rb b/lib/puppet/provider/user/aix.rb index c231da816..032d2b536 100755 --- a/lib/puppet/provider/user/aix.rb +++ b/lib/puppet/provider/user/aix.rb @@ -1,351 +1,353 @@ # -# User Puppet provider for AIX. It uses standar commands to manage users: +# User Puppet provider for AIX. It uses standard 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 # 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 + # User attributes to ignore from AIX output. 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 + # :from Method to adapt aix command value to puppet property. Optional self.attribute_mapping = [ #:name => :name, - {:aix_attr => :pgrp, :puppet_prop => :gid, + {: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, + {: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}, + {:aix_attr => :maxage, :puppet_prop => :password_max_age}, + {:aix_attr => :minage, :puppet_prop => :password_min_age}, + {:aix_attr => :attributes, :puppet_prop => :attributes}, ] #-------------- - # Command lines + # Command definition + + # Return the IA module arguments based on the resource param ia_load_module def get_ia_module_args if @resource[:ia_load_module] ["-R", @resource[:ia_load_module].to_s] else [] end end + # List groups and Ids 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.= 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 + # Get modify command. Set translate=false if no mapping must be used. + # Needed for special properties like "attributes" + def modifycmd(hash = property_hash) + args = self.hash2args(hash) 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 + # Get the group gid from its name 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) + cmd = modifycmd({param => filter_attributes(attr_hash)}) 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