summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2005-09-07 05:28:58 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2005-09-07 05:28:58 +0000
commit4cc12a85baf2617ad9d60d521249e24ffdefcd53 (patch)
tree3873e349624c4ad157d18a10195401ae0982dddd /lib
parent9e4ed0ca8887c99cd5f29b6f7d0a9eaa950c0693 (diff)
downloadpuppet-4cc12a85baf2617ad9d60d521249e24ffdefcd53.tar.gz
puppet-4cc12a85baf2617ad9d60d521249e24ffdefcd53.tar.xz
puppet-4cc12a85baf2617ad9d60d521249e24ffdefcd53.zip
finishing up user and group support for now
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@633 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/statechange.rb6
-rw-r--r--lib/puppet/transaction.rb1
-rwxr-xr-xlib/puppet/type/group.rb9
-rwxr-xr-xlib/puppet/type/user.rb210
4 files changed, 140 insertions, 86 deletions
diff --git a/lib/puppet/statechange.rb b/lib/puppet/statechange.rb
index ac10dc301..af066a773 100644
--- a/lib/puppet/statechange.rb
+++ b/lib/puppet/statechange.rb
@@ -48,7 +48,7 @@ module Puppet
if event.nil?
#event = @state.parent.class.name.id2name + "_changed"
# they didn't actually change anything
- return
+ return nil
elsif ! event.is_a?(Symbol)
Puppet.warning "State '%s' returned invalid event '%s'; resetting to default" %
[@state.class,event]
@@ -111,6 +111,10 @@ module Puppet
unless @state.insync?
Puppet.notice "Rolling %s backward" % self
return self.go
+ else
+ Puppet.debug "rollback is already in sync: %s vs. %s" %
+ [@state.is.inspect, @state.should.inspect]
+ return nil
end
#raise "Moving statechanges backward is currently unsupported"
diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb
index 2e726df0b..f0ef8469d 100644
--- a/lib/puppet/transaction.rb
+++ b/lib/puppet/transaction.rb
@@ -115,6 +115,7 @@ class Transaction
def rollback
events = @changes.collect { |change|
if change.is_a?(Puppet::StateChange)
+ # skip changes that were never actually run
next unless change.run
#change.transaction = self
begin
diff --git a/lib/puppet/type/group.rb b/lib/puppet/type/group.rb
index 38a56dc31..fc8b7555d 100755
--- a/lib/puppet/type/group.rb
+++ b/lib/puppet/type/group.rb
@@ -100,7 +100,12 @@ module Puppet
:name
]
- @doc = " "
+ @doc = "Manage groups. This type can only create groups. Group
+ membership must be managed on individual users."
+
+ @paramdoc[:name] = "The group name. While naming limitations vary by
+ system, it is advisable to keep the name to the degenerate limitations,
+ which is a maximum of 8 characters beginning with a letter."
@name = :group
@namevar = :name
@@ -109,7 +114,7 @@ module Puppet
begin
@groupinfo = Etc.getgrnam(self[:name])
rescue ArgumentError => detail
- # leave groupinfo as nil
+ @groupinfo = nil
end
end
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index cc7bbadaa..c4b31ed3e 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -7,43 +7,95 @@ require 'puppet/type/state'
module Puppet
class State
class UserState < Puppet::State
- @@userinfo = nil
-
class << self
- attr_accessor :infomethod
-
- def getinfo(refresh = false)
- if @@userinfo.nil? or refresh == true
- begin
- @@userinfo = Etc.getpwnam(@parent[:name])
- rescue ArgumentError => detail
- @@userinfo = :notfound
- end
+ attr_accessor :flag
+ def infomethod
+ if defined? @infomethod and @infomethod
+ return @infomethod
+ else
+ return @name
+ end
+ end
+ end
+
+ def create
+ obj = @parent.getinfo
+
+ cmd = nil
+ event = nil
+ if @should == :notfound
+ # we need to remove the object...
+ if obj.nil?
+ # the user already doesn't exist
+ return nil
end
- @@userinfo
+ cmd = ["userdel", @parent.name]
+ type = "delete"
+ else
+ unless obj.nil?
+ raise Puppet::DevError,
+ "Got told to create a user that already exists"
+ end
+ # we're creating the user
+
+ # i can just tell i'm going to regret this
+ # why doesn't POSIX include interfaces for adding users
+ # and groups? it's stupid
+ cmd = ["useradd"]
+ @parent.eachstate { |state|
+ # the value needs to be quoted, mostly because -c might
+ # have spaces in it
+ cmd << state.class.flag << "'%s'" % state.should
+ }
+ cmd << @parent.name
+ type = "create"
+ end
+
+ output = %x{#{cmd.join(" ")} 2>&1}
+
+ unless $? == 0
+ raise Puppet::Error, "Could not %s group %s: %s" %
+ [type, @parent.name, output]
end
+
+ return "user_#{type}d".intern
end
def retrieve
- info = self.class.getinfo(true)
+ if info = @parent.getinfo(true)
+ @is = info.send(self.class.infomethod)
+ else
+ @is = :notfound
+ end
+ end
- method = self.class.infomethod || self.class.name
+ def sync
+ obj = @parent.getinfo
- unless method
- raise Puppet::DevError,
- "Could not retrieve info method for state %s" % self.class.name
+ # if the user either does not or should not exist...
+ # yes, it's a badly named method
+ if obj.nil? or @should == :notfound
+ return self.create
end
- unless info.respond_to?(method)
- raise Puppet::DevError, "UserInfo object does not respond to %s" %
- method
+ # there's a possibility that we created the user in this session
+ # so verify that we're actually out of sync
+ if self.insync?
+ return nil
end
+ cmd = [
+ "usermod", self.class.flag, "'%s'" % @should, @parent.name
+ ].join(" ")
- @is = info.send(method)
- end
+ output = %x{#{cmd} 2>&1}
- def sync
+ unless $? == 0
+ raise Puppet::Error, "Could not modify %s on user %s: %s" %
+ [self.class.name, @parent.name, output]
+ end
+
+ return :user_modified
end
end
@@ -53,11 +105,13 @@ module Puppet
automatically, which will likely result in the same user having
different IDs on different systems, which is not recommended."
@name = :uid
+ @flag = "-u"
end
class UserGID < UserState
@doc = "The user's primary group. Can be specified numerically or by name."
@name = :gid
+ @flag = "-g"
def should=(gid)
method = :getgrgid
@@ -79,88 +133,54 @@ module Puppet
@should = ginfo.gid
end
-
- def sync
- return :executed_command
- end
end
class UserComment < UserState
- @doc = "The expected return code. An error will be returned if the
- executed command returns something else."
+ @doc = "A description of the user. Generally is a user's full name."
@name = :comment
-
- def retrieve
- end
-
- def sync
- return :executed_command
- end
+ @infomethod = :gecos
+ @flag = "-c"
end
class UserHome < UserState
- @doc = "The expected return code. An error will be returned if the
- executed command returns something else."
+ @doc = "The home directory of the user. The directory must be created
+ separately and is not currently checked for existence."
@name = :home
-
- def retrieve
- end
-
- def sync
- return :executed_command
- end
+ @infomethod = :dir
+ @flag = "-d"
end
class UserShell < UserState
- @doc = "The expected return code. An error will be returned if the
- executed command returns something else."
+ @doc = "The user's login shell. The shell must exist and be
+ executable."
@name = :shell
-
- def retrieve
- end
-
- def sync
- return :executed_command
- end
+ @flag = "-s"
end
+ # these three states are all implemented differently on each platform, so i'm
+ # disabling them for now
+
+ # FIXME Puppet::State::UserLocked is currently non-functional
class UserLocked < UserState
@doc = "The expected return code. An error will be returned if the
executed command returns something else."
@name = :locked
-
- def retrieve
- end
-
- def sync
- return :executed_command
- end
end
+ # FIXME Puppet::State::UserExpire is currently non-functional
class UserExpire < UserState
@doc = "The expected return code. An error will be returned if the
executed command returns something else."
@name = :expire
-
- def retrieve
- end
-
- def sync
- return :executed_command
- end
+ @flag = "-e"
end
+ # FIXME Puppet::State::UserInactive is currently non-functional
class UserInactive < UserState
@doc = "The expected return code. An error will be returned if the
executed command returns something else."
@name = :inactive
-
- def retrieve
- end
-
- def sync
- return :executed_command
- end
+ @flag = "-f"
end
end
@@ -172,25 +192,49 @@ module Puppet
Puppet::State::UserGID,
Puppet::State::UserComment,
Puppet::State::UserHome,
- Puppet::State::UserShell,
- Puppet::State::UserLocked,
- Puppet::State::UserExpire,
- Puppet::State::UserInactive
+ Puppet::State::UserShell
]
@parameters = [
:name
]
- @doc = "
- "
+ @paramdoc[:name] = "User name. While limitations are determined for
+ each operating system, it is generally a good idea to keep to the
+ degenerate 8 characters, beginning with a letter."
+
+ @doc = "Manage users. Currently can create and modify users, but cannot
+ delete them. Theoretically all of the parameters are optional,
+ but if no parameters are specified the comment will be set to the
+ user name in order to make the internals work out correctly."
@name = :user
@namevar = :name
+ def getinfo(refresh = false)
+ if @userinfo.nil? or refresh == true
+ begin
+ @userinfo = Etc.getpwnam(self[:name])
+ rescue ArgumentError => detail
+ @userinfo = nil
+ end
+ end
+
+ @userinfo
+ end
+
+ def initialize(hash)
+ @userinfo = nil
+ super
+
+ if @states.empty?
+ self[:comment] = self[:name]
+ end
+ end
+
def retrieve
- info = Puppet::State::UserState.getinfo
+ info = self.getinfo(true)
- if info == :notfound
+ if info.nil?
# the user does not exist
@states.each { |name, state|
state.is = :notfound