diff options
-rw-r--r-- | lib/puppet/config.rb | 18 | ||||
-rwxr-xr-x | lib/puppet/type/group.rb | 1 | ||||
-rwxr-xr-x | lib/puppet/type/nameservice.rb | 186 | ||||
-rw-r--r-- | lib/puppet/type/nameservice/netinfo.rb | 232 | ||||
-rw-r--r-- | lib/puppet/type/nameservice/objectadd.rb | 146 | ||||
-rw-r--r-- | lib/puppet/type/nameservice/posix.rb | 12 | ||||
-rw-r--r-- | lib/puppet/type/nameservice/pw.rb | 107 | ||||
-rwxr-xr-x | lib/puppet/type/user.rb | 2 |
8 files changed, 12 insertions, 692 deletions
diff --git a/lib/puppet/config.rb b/lib/puppet/config.rb index cc6383fc9..81ec4fe85 100644 --- a/lib/puppet/config.rb +++ b/lib/puppet/config.rb @@ -386,18 +386,20 @@ class Config def section_to_transportable(section, done = nil, includefiles = true) done ||= Hash.new { |hash, key| hash[key] = {} } objects = [] - persection(section) { |obj| + persection(section) do |obj| if @config[:mkusers] and @config[:mkusers].value - [:owner, :group].each { |attr| + [:owner, :group].each do |attr| type = nil if attr == :owner type = :user else type = attr end + # If a user and/or group is set, then make sure we're + # managing that object if obj.respond_to? attr and name = obj.send(attr) - # Skip owners and groups we've already done, but tag them with - # our section if necessary + # Skip owners and groups we've already done, but tag + # them with our section if necessary if done[type].include?(name) tags = done[type][name].tags unless tags.include?(section) @@ -412,11 +414,15 @@ class Config newobj = TransObject.new(name, type.to_s) newobj.tags = ["puppet", "configuration", section] newobj[:ensure] = "present" + # Set the group appropriately for the user + if type == :user + newobj[:gid] = Puppet[:group] + end done[type][name] = newobj objects << newobj end end - } + end end if obj.respond_to? :to_transportable @@ -433,7 +439,7 @@ class Config end end end - } + end bucket = Puppet::TransBucket.new bucket.type = section diff --git a/lib/puppet/type/group.rb b/lib/puppet/type/group.rb index b03f57907..e2b8dfcb9 100755 --- a/lib/puppet/type/group.rb +++ b/lib/puppet/type/group.rb @@ -9,7 +9,6 @@ require 'etc' require 'facter' require 'puppet/type/state' -require 'puppet/type/nameservice' module Puppet newtype(:group) do diff --git a/lib/puppet/type/nameservice.rb b/lib/puppet/type/nameservice.rb deleted file mode 100755 index 6db2ff083..000000000 --- a/lib/puppet/type/nameservice.rb +++ /dev/null @@ -1,186 +0,0 @@ -require 'puppet/type' - -module Puppet -class Type - class NSSType < Puppet::Type - class << self - attr_reader :parentstate, :parentmodule - - # Seems a lot like this should be elsewhere, - # but we'd have to have a different parent class for - # netinfo types if that were the case. - attr_accessor :netinfodir - - # Create an instance for every object that exists on the machine - def list - listbyname.collect do |name| - obj = nil - check = @states.collect { |st| st.name } - if obj = self[name] - obj[:check] = check - else - # unless it exists, create it as an unmanaged object - obj = self.create(:name => name, :check => check) - end - - next unless obj # In case there was an error somewhere - - #obj.retrieve - obj - end - end - - def newstate(*args, &block) - s = super(*args, &block) - - if s.respond_to?(:finish) - s.finish - end - end - end - end -end - -class State - # This is the state that all other Nameservice states descend from. It sets - # the standard for how one interacts with these state objects, but it leaves - # out any implementation details. See the 'posix' stuff for the basics - # on how to retrieve information on most systems, but any adding of information - # is done specially per-system (e.g., netinfo, useradd, adduser). - class NSSState < Puppet::State - class << self - # Are all changes to states done in one step or do all states need - # to be synced individually? This differentiates between netinfo, - # in which creation cannot be used to fill out information, and - # things like useradd, in which creation can be done with all - # information in one swell foop. - def allatonce? - #Puppet.info "Returning allatonce %s" % @allatonce - if defined? @allatonce - return @allatonce - else - return false - end - end - - # Yes, this value will autogenerate. - def isautogen - @isautogen = true - end - - def noautogen - @isautogen = false - end - - # Can we autogenerate a value for this field? If a required field - # can be autogenerated then we don't require a value. - def autogen? - if defined? @isautogen and @isautogen - return true - else - return false - end - end - - # Yes, this field is optional - def isoptional - @isoptional = true - end - - # Is this field optional? Defaults to false. - def isoptional? - if defined? @isoptional - return @isoptional - else - return false - end - end - - # What method is used to retrieve the value from the POSIX struct? - # Really, these method names should be stored in this class somewhere, - # in a map or something, but then I would have to differentiate - # between the different posix classes (e.g., user and group). In the - # end, we're _only_ using classes that _do_ have posix structs, - # so we might as well store the method in the class definition, - # rather than forcing it to be abstracted out or whatever. - def posixmethod - if defined? @posixmethod - return @posixmethod - else - return self.name - end - end - end - - # We use the POSIX interfaces to retrieve all information, so we don't - # have to worry about abstracting that across the system. Any class - # can still override this, but it should work for the vast majority of - # cases. - def retrieve - if obj = @parent.getinfo(true) - if method = self.class.posixmethod || self.class.name - @is = obj.send(method) - else - self.devfail "%s has no posixmethod" % self.class - end - else - @is = :absent - end - end - - # Sync the information. - def sync - event = nil - # they're in sync some other way - if self.insync? - return nil - end - if @is == :absent - self.retrieve - if self.insync? - return nil - end - end - - unless @parent.exists? - self.devfail "%s %s does not exist; cannot set %s" % - [@parent.class.name, @parent.name, self.class.name] - end - - # this needs to be set either by the individual state - # or its parent class - cmd = self.modifycmd - - self.debug "Executing %s" % cmd.inspect - - output = %x{#{cmd} 2>&1} - - - unless $? == 0 - self.fail "Could not modify %s on %s %s: %s" % - [self.class.name, @parent.class.name, - @parent.name, output] - end - - if event - return event - else - return "#{@parent.class.name}_modified".intern - end - end - end -end -end - -# Here's where we decide what type of objects we'll be dealing with. -case Facter["operatingsystem"].value -when "Darwin": - require 'puppet/type/nameservice/netinfo' -when "FreeBSD": - require 'puppet/type/nameservice/pw' -else - require 'puppet/type/nameservice/objectadd' -end - - -# $Id$ diff --git a/lib/puppet/type/nameservice/netinfo.rb b/lib/puppet/type/nameservice/netinfo.rb deleted file mode 100644 index 6230aa31b..000000000 --- a/lib/puppet/type/nameservice/netinfo.rb +++ /dev/null @@ -1,232 +0,0 @@ -# Manage NetInfo POSIX objects. Probably only used on OS X, but I suppose -# it could be used elsewhere. - -require 'puppet' -require 'puppet/type/nameservice/posix' - -module Puppet - module NameService - module NetInfo - # Verify that we've got all of the commands we need. - def self.test - system("which niutil > /dev/null 2>&1") - - if $? == 0 - return true - else - Puppet.err "Could not find niutil" - return false - end - - system("which nireport > /dev/null 2>&1") - - if $? == 0 - return true - else - Puppet.err "Could not find nireport" - return false - end - end - - # Does the object already exist? - def self.exists?(obj) - cmd = "nidump -r /%s/%s /" % - [obj.class.netinfodir, obj[:name]] - - output = %x{#{cmd} 2>/dev/null} - if output == "" - return false - else - #Puppet.debug "%s exists: %s" % [obj.name, output] - return true - end - end - - # Attempt to flush the database, but this doesn't seem to work at all. - def self.flush - output = %x{lookupd -flushcache 2>&1} - - if $? != 0 - Puppet.err "Could not flush lookupd cache: %s" % output - end - end - - # The state responsible for handling netinfo objects. Because they - # are all accessed using the exact same interface, we can just - # abstract the differents using a simple map where necessary - # (the netinfokeymap). - class NetInfoState < Puppet::State::NSSState - # Similar to posixmethod, what key do we use to get data? Defaults - # to being the object name. - def self.netinfokey - if defined? @netinfokey - return @netinfokey - else - return self.name - end - end - - def self.setkey(key) - @netinfokey = key - end - - def self.finish - @allatonce = false - case self.name - when :comment: setkey "realname" - when :uid: - noautogen - when :gid: - noautogen - end - end - - # Retrieve the data, yo. - # FIXME This should retrieve as much information as possible, - # rather than retrieving it one at a time. - def retrieve - NetInfo.flush - dir = @parent.class.netinfodir - cmd = ["nireport", "/", "/%s" % dir, "name"] - - if key = self.class.netinfokey - cmd << key.to_s - else - raise Puppet::DevError, - "Could not find netinfokey for state %s" % - self.class.name - end - self.debug "Executing %s" % cmd.join(" ").inspect - - %x{#{cmd.join(" ")} 2>&1}.split("\n").each { |line| - if line =~ /^(\w+)\s+(.+)$/ - name = $1 - value = $2.sub(/\s+$/, '') - - if name == @parent[:name] - if value =~ /^[-0-9]+$/ - @is = Integer(value) - else - @is = value - end - end - else - raise Puppet::DevError, "Could not match %s" % line - end - } - - unless defined? @is - @is = :absent - end - end - - # The list of all groups the user is a member of. Different - # user mgmt systems will need to override this method. - def grouplist - groups = [] - - user = @parent[:name] - # Retrieve them all from netinfo - open("| nireport / /groups name users") do |file| - file.each do |line| - name, members = line.split(/\s+/) - next unless members - next if members =~ /NoValue/ - members = members.split(",") - - if members.include? user - groups << name - end - end - end - - groups - end - - # This is really lame. We have to iterate over each - # of the groups and add us to them. - def setgrouplist(groups) - groups = groups.split(/\s*,\s*/) - # Get just the groups we need to modify - diff = groups - @is - - data = {} - open("| nireport / /groups name users") do |file| - file.each do |line| - name, members = line.split(/\s+/) - - if members.nil? or members =~ /NoValue/ - data[name] = [] - else - # Add each diff group's current members - data[name] = members.split(/,/) - end - end - end - - user = @parent[:name] - data.each do |name, members| - if members.include? user and groups.include? name - # I'm in the group and should be - next - elsif members.include? user - # I'm in the group and shouldn't be - setuserlist(name, members - [user]) - elsif groups.include? name - # I'm not in the group and should be - setuserlist(name, members + [user]) - else - # I'm not in the group and shouldn't be - next - end - end - end - - def setuserlist(group, list) - cmd = "niutil -createprop / /groups/%s users %s" % - [group, list.join(",")] - output = %x{#{cmd}} - end - - # How to add an object. - def addcmd - creatorcmd("-create") - end - - def creatorcmd(arg) - cmd = ["niutil"] - cmd << arg - - cmd << "/" << "/%s/%s" % - [@parent.class.netinfodir, @parent[:name]] - - #if arg == "-create" - # return [cmd.join(" "), self.modifycmd].join(";") - #else - return cmd.join(" ") - #end - end - - def deletecmd - creatorcmd("-destroy") - end - - def modifycmd - cmd = ["niutil"] - - cmd << "-createprop" << "/" << "/%s/%s" % - [@parent.class.netinfodir, @parent[:name]] - - if key = self.class.netinfokey - cmd << key << "'%s'" % self.should - else - raise Puppet::DevError, - "Could not find netinfokey for state %s" % - self.class.name - end - cmd.join(" ") - end - end - end - end -end diff --git a/lib/puppet/type/nameservice/objectadd.rb b/lib/puppet/type/nameservice/objectadd.rb deleted file mode 100644 index f9b05f4a2..000000000 --- a/lib/puppet/type/nameservice/objectadd.rb +++ /dev/null @@ -1,146 +0,0 @@ -require 'puppet' - -module Puppet - module NameService - module ObjectAdd - # Verify that we've got the commands necessary to manage flat files. - def self.test - system("which groupadd > /dev/null 2>&1") - - if $? == 0 - return true - else - Puppet.err "Could not find groupadd" - return false - end - end - - # Does the object already exist? - def self.exists?(obj) - if obj.getinfo(true) - return true - else - return false - end - end - - # The base state class for <object>add operations. - class ObjectAddState < Puppet::State::NSSState - class << self - # Determine the flag to pass to our command. - def objectaddflag - unless defined? @objectaddflag - # Else, return the first letter of the name. I have to - # user a range here, else the character will show up - # as a number, rather than as a string, for some reason. - @objectaddflag = "-" + self.name.to_s[0,1] - Puppet.debug "Setting flag on %s to %s" % - [self.name, @objectaddflag] - end - return @objectaddflag - end - - # Set the flag manually. - def setflag(value) - @objectaddflag = value - end - end - end - - # The state class for doing group operations using groupadd or whatever. - # I could probably have abstracted the User and Group classes into - # a single class, but eh, it just didn't seem worth it. - class ObjectAddGroup < ObjectAddState - class << self - # This is hackish, but hey, it works. - def finish - @allatonce = true - end - end - - def addcmd - cmd = ["groupadd"] - if gid = @parent.should(:gid) - unless gid == :auto - cmd << @parent.state(:gid).class.objectaddflag << gid - end - end - if @parent[:allowdupe] == :true - cmd << "-o" - end - cmd << @parent[:name] - - return cmd.join(" ") - end - - def deletecmd - "groupdel %s" % @parent[:name] - end - - def modifycmd - cmd = ["groupmod", - self.class.objectaddflag, - "'%s'" % self.should] - if @parent[:allowdupe] == :true - cmd << "-o" - end - cmd << @parent[:name] - - return cmd.join(" ") - end - end - - # The class for adding users using 'adduser'. - class ObjectAddUser < ObjectAddState - class << self - # This is hackish, but hey, it works. - def finish - @allatonce = true - case self.name - when :home: setflag "-d" - when :groups: setflag "-G" - end - end - end - def addcmd - cmd = ["useradd"] - @parent.eachstate { |state| - next if state.name == :ensure - # the value needs to be quoted, mostly because -c might - # have spaces in it - cmd << state.class.objectaddflag << "'%s'" % state.should - } - # stupid fedora - case Facter["operatingsystem"].value - when "Fedora", "RedHat": - cmd << "-M" - else - end - if @parent[:allowdupe] == :true - cmd << "-o" - end - - cmd << @parent[:name] - - cmd.join(" ") - end - - def deletecmd - ["userdel", @parent[:name]].join(" ") - end - - def modifycmd - cmd = ["usermod", - self.class.objectaddflag, - "'%s'" % self.should] - if @parent[:allowdupe] == :true - cmd << "-o" - end - cmd << @parent[:name] - - return cmd.join(" ") - end - end - end - end -end diff --git a/lib/puppet/type/nameservice/posix.rb b/lib/puppet/type/nameservice/posix.rb deleted file mode 100644 index cf8c371ef..000000000 --- a/lib/puppet/type/nameservice/posix.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet' -require 'puppet/type/nameservice' - -module Puppet - class State - # The lowest-level state class for managing NSS/POSIX information. It - # at least knows how to retrieve information, but it does not know how - # to sync anything. - class POSIXState < NSSState - end - end -end diff --git a/lib/puppet/type/nameservice/pw.rb b/lib/puppet/type/nameservice/pw.rb deleted file mode 100644 index 63d5e2e50..000000000 --- a/lib/puppet/type/nameservice/pw.rb +++ /dev/null @@ -1,107 +0,0 @@ -require 'puppet' -require 'puppet/type/nameservice/objectadd' - -module Puppet - module NameService - module PW - # Verify that we've got the commands necessary to manage flat files. - def self.test - system("which pw > /dev/null 2>&1") - - if $? == 0 - return true - else - Puppet.err "Could not find pw" - return false - end - end - - # Does the object already exist? - def self.exists?(obj) - if obj.getinfo(true) - return true - else - return false - end - end - - # The state class for doing group operations using groupadd or whatever. - # I could probably have abstracted the User and Group classes into - # a single class, but eh, it just didn't seem worth it. - class PWGroup < ObjectAdd::ObjectAddGroup - def addcmd - cmd = ["pw", "groupadd", @parent[:name]] - if gid = @parent.should(:gid) - unless gid == :auto - cmd << @parent.state(:gid).class.objectaddflag << gid - end - end - - # Apparently, contrary to the man page, groupadd does - # not accept -o. - #if @parent[:allowdupe] == :true - # cmd << "-o" - #end - - return cmd.join(" ") - end - - def deletecmd - "pw groupdel %s" % @parent[:name] - end - - def modifycmd - cmd = [ - "pw", - "groupmod", - @parent[:name], - self.class.objectaddflag, - "'%s'" % self.should - ] - return cmd.join(" ") - end - end - - # The class for adding users using 'adduser'. - class PWUser < ObjectAdd::ObjectAddUser - def addcmd - cmd = ["pw", "useradd", @parent[:name], "-w", "no"] - @parent.eachstate { |state| - next if state.name == :ensure - # the value needs to be quoted, mostly because -c might - # have spaces in it - cmd << state.class.objectaddflag << "'%s'" % state.should - } - # stupid fedora - case Facter["operatingsystem"].value - when "Fedora", "RedHat": - cmd << "-M" - end - - if @parent[:allowdupe] == :true - cmd << "-o" - end - - cmd.join(" ") - end - - def deletecmd - ["pw", "userdel", @parent[:name]].join(" ") - end - - def modifycmd - cmd = [ - "pw", - "usermod", - @parent[:name], - "-w", "no", - self.class.objectaddflag, - "'%s'" % self.should - ] - - return cmd.join(" ") - end - end - end - end -end diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb index 3a78d9669..8905b8d1d 100755 --- a/lib/puppet/type/user.rb +++ b/lib/puppet/type/user.rb @@ -1,7 +1,6 @@ require 'etc' require 'facter' require 'puppet/type/state' -require 'puppet/type/nameservice' module Puppet newtype(:user) do @@ -166,7 +165,6 @@ module Puppet end super end - end newstate(:comment) do |