@ -32,12 +32,12 @@ options:
- Name of the user to create , remove or modify .
- Name of the user to create , remove or modify .
required : true
required : true
aliases : [ user ]
aliases : [ user ]
comment :
description :
- Optionally sets the description ( aka I ( GECOS ) ) of user account .
uid :
uid :
description :
description :
- Optionally sets the I ( UID ) of the user .
- Optionally sets the I ( UID ) of the user .
comment :
description :
- Optionally sets the description ( aka I ( GECOS ) ) of user account .
hidden :
hidden :
required : false
required : false
type : bool
type : bool
@ -47,8 +47,7 @@ options:
version_added : " 2.6 "
version_added : " 2.6 "
non_unique :
non_unique :
description :
description :
- Optionally when used with the - u option , this option allows to
- Optionally when used with the - u option , this option allows to change the user ID to a non - unique value .
change the user ID to a non - unique value .
type : bool
type : bool
default : " no "
default : " no "
version_added : " 1.1 "
version_added : " 1.1 "
@ -67,16 +66,14 @@ options:
now it should be able to accept YAML lists also .
now it should be able to accept YAML lists also .
append :
append :
description :
description :
- If C ( yes ) , will only add groups , not set them to just the list
- If C ( yes ) , will only add groups , not set them to just the list in I ( groups ) .
in I ( groups ) .
type : bool
type : bool
default : " no "
default : " no "
shell :
shell :
description :
description :
- Optionally set the user ' s shell.
- Optionally set the user ' s shell.
- On Mac OS X , before version 2.5 , the default shell for non - system users was
- On Mac OS X , before version 2.5 , the default shell for non - system users was / usr / bin / false .
/ usr / bin / false . Since 2.5 , the default shell for non - system users on
Since 2.5 , the default shell for non - system users on Mac OS X is / bin / bash .
Mac OS X is / bin / bash .
home :
home :
description :
description :
- Optionally set the user ' s home directory.
- Optionally set the user ' s home directory.
@ -98,39 +95,38 @@ options:
create_home :
create_home :
description :
description :
- Unless set to C ( no ) , a home directory will be made for the user
- Unless set to C ( no ) , a home directory will be made for the user
when the account is created or if the home directory does not
when the account is created or if the home directory does not exist .
exist .
- Changed from C ( createhome ) to C ( create_home ) in version 2.5 .
- Changed from C ( createhome ) to C ( create_home ) in version 2.5 .
type : bool
type : bool
default : ' yes '
default : ' yes '
aliases : [ ' createhome ' ]
aliases : [ ' createhome ' ]
move_home :
move_home :
description :
description :
- If set to C ( yes ) when used with C ( home = ) , attempt to move the
- If set to C ( yes ) when used with C ( home = ) , attempt to move the user ' s old home
user ' s home directory to the specified directory if it isn ' t there
directory to the specified directory if it isn ' t there already and the old home exists.
already .
type : bool
type : bool
default : " no "
default : " no "
system :
system :
description :
description :
- When creating an account , setting this to C ( yes ) makes the user a
- When creating an account C ( state = present ) , setting this to C ( yes ) makes the user a system account .
system account . This setting cannot be changed on existing users .
This setting cannot be changed on existing users .
type : bool
type : bool
default : " no "
default : " no "
force :
force :
description :
description :
- When used with C ( state = absent ) , behavior is as with C ( userdel - - force ) .
- This only affects C ( state = absent ) , it forces removal of the user and associated directories on supported platforms .
The behavior is the same as C ( userdel - - force ) , check the man page for C ( userdel ) on your system for details and support .
type : bool
type : bool
default : " no "
default : " no "
login_class :
description :
- Optionally sets the user ' s login class for FreeBSD, DragonFlyBSD, OpenBSD and
NetBSD systems .
remove :
remove :
description :
description :
- When used with C ( state = absent ) , behavior is as with C ( userdel - - remove ) .
- This only affects C ( state = absent ) , it attempts to remove directories associated with the user .
The behavior is the same as C ( userdel - - remove ) , check the man page for details and support .
type : bool
type : bool
default : " no "
default : " no "
login_class :
description :
- Optionally sets the user ' s login class, a feature of most BSD OSs.
generate_ssh_key :
generate_ssh_key :
description :
description :
- Whether to generate a SSH key for the user in question .
- Whether to generate a SSH key for the user in question .
@ -176,7 +172,8 @@ options:
expires :
expires :
description :
description :
- An expiry time for the user in epoch , it will be ignored on platforms that do not support this .
- An expiry time for the user in epoch , it will be ignored on platforms that do not support this .
Currently supported on Linux , FreeBSD , and DragonFlyBSD .
Currently supported on GNU / Linux , FreeBSD , and DragonFlyBSD .
- Since version 2.6 you can remove the expiry time specify a negative value . Currently supported on GNU / Linux and FreeBSD .
version_added : " 1.9 "
version_added : " 1.9 "
password_lock :
password_lock :
description :
description :
@ -231,6 +228,12 @@ EXAMPLES = '''
shell : / bin / zsh
shell : / bin / zsh
groups : developers
groups : developers
expires : 1422403387
expires : 1422403387
- name : starting at version 2.6 , modify user , remove expiry time
user :
name : james18
expires : - 1
'''
'''
import grp
import grp
@ -311,11 +314,11 @@ class User(object):
if module . params [ ' groups ' ] is not None :
if module . params [ ' groups ' ] is not None :
self . groups = ' , ' . join ( module . params [ ' groups ' ] )
self . groups = ' , ' . join ( module . params [ ' groups ' ] )
if module . params [ ' expires ' ] :
if module . params [ ' expires ' ] is not None :
try :
try :
self . expires = time . gmtime ( module . params [ ' expires ' ] )
self . expires = time . gmtime ( module . params [ ' expires ' ] )
except Exception as e :
except Exception as e :
module . fail_json ( msg = " Invalid expires time %s : %s " % ( self . expires , to_native ( e ) ) )
module . fail_json ( msg = " Invalid value for ' expires ' %s : %s " % ( self . expires , to_native ( e ) ) )
if module . params [ ' ssh_key_file ' ] is not None :
if module . params [ ' ssh_key_file ' ] is not None :
self . ssh_file = module . params [ ' ssh_key_file ' ]
self . ssh_file = module . params [ ' ssh_key_file ' ]
@ -409,7 +412,7 @@ class User(object):
cmd . append ( ' -s ' )
cmd . append ( ' -s ' )
cmd . append ( self . shell )
cmd . append ( self . shell )
if self . expires :
if self . expires is not None :
cmd . append ( ' -e ' )
cmd . append ( ' -e ' )
cmd . append ( time . strftime ( self . DATE_FORMAT , self . expires ) )
cmd . append ( time . strftime ( self . DATE_FORMAT , self . expires ) )
@ -532,17 +535,22 @@ class User(object):
cmd . append ( ' -s ' )
cmd . append ( ' -s ' )
cmd . append ( self . shell )
cmd . append ( self . shell )
if self . expires :
if self . expires is not None :
current_expires = self . user_password ( ) [ 1 ]
# Convert days since Epoch to seconds since Epoch as struct_time
current_expires = int ( self . user_password ( ) [ 1 ] )
total_seconds = int ( current_expires ) * 86400
current_expires = time . gmtime ( total_seconds )
# Compare year, month, and day only
if self . expires < time . gmtime ( 0 ) :
if current_expires [ : 3 ] != self . expires [ : 3 ] :
if current_expires > 0 :
cmd . append ( ' -e ' )
cmd . append ( ' -e ' )
cmd . append ( time . strftime ( self . DATE_FORMAT , self . expires ) )
cmd . append ( ' ' )
else :
# Convert days since Epoch to seconds since Epoch as struct_time
current_expire_date = time . gmtime ( current_expires * 86400 )
# Current expires is negative or we compare year, month, and day only
if current_expires < = 0 or current_expire_date [ : 3 ] != self . expires [ : 3 ] :
cmd . append ( ' -e ' )
cmd . append ( time . strftime ( self . DATE_FORMAT , self . expires ) )
if self . password_lock :
if self . password_lock :
cmd . append ( ' -L ' )
cmd . append ( ' -L ' )
@ -647,7 +655,7 @@ class User(object):
for line in open ( self . SHADOWFILE ) . readlines ( ) :
for line in open ( self . SHADOWFILE ) . readlines ( ) :
if line . startswith ( ' %s : ' % self . name ) :
if line . startswith ( ' %s : ' % self . name ) :
passwd = line . split ( ' : ' ) [ 1 ]
passwd = line . split ( ' : ' ) [ 1 ]
expires = line . split ( ' : ' ) [ self . SHADOWFILE_EXPIRE_INDEX ]
expires = line . split ( ' : ' ) [ self . SHADOWFILE_EXPIRE_INDEX ] or - 1
return passwd , expires
return passwd , expires
def get_ssh_key_path ( self ) :
def get_ssh_key_path ( self ) :
@ -845,7 +853,7 @@ class FreeBsdUser(User):
cmd . append ( ' -L ' )
cmd . append ( ' -L ' )
cmd . append ( self . login_class )
cmd . append ( self . login_class )
if self . expires :
if self . expires is not None :
cmd . append ( ' -e ' )
cmd . append ( ' -e ' )
cmd . append ( time . strftime ( self . DATE_FORMAT , self . expires ) )
cmd . append ( time . strftime ( self . DATE_FORMAT , self . expires ) )
@ -946,13 +954,22 @@ class FreeBsdUser(User):
new_groups = groups | set ( current_groups )
new_groups = groups | set ( current_groups )
cmd . append ( ' , ' . join ( new_groups ) )
cmd . append ( ' , ' . join ( new_groups ) )
if self . expires :
if self . expires is not None :
current_expires = time . gmtime ( int ( self . user_password ( ) [ 1 ] ) )
current_expires = int ( self . user_password ( ) [ 1 ] )
if self . expires < time . gmtime ( 0 ) :
if current_expires > 0 :
cmd . append ( ' -e ' )
cmd . append ( ' 0 ' )
else :
# Convert days since Epoch to seconds since Epoch as struct_time
current_expire_date = time . gmtime ( current_expires )
# Compare year, month, and day only
# C urrent expires is negative or we c ompare year, month, and day only
if current_expires [ : 3 ] != self . expires [ : 3 ] :
if current_expires < = 0 or current_expire_date [ : 3 ] != self . expires [ : 3 ] :
cmd . append ( ' -e ' )
cmd . append ( ' -e ' )
cmd . append ( time . strftime ( self . DATE_FORMAT , self . expires ) )
cmd . append ( time . strftime ( self . DATE_FORMAT , self . expires ) )
# modify the user if cmd will do anything
# modify the user if cmd will do anything
if cmd_len != len ( cmd ) :
if cmd_len != len ( cmd ) :