Skip to content

Commit

Permalink
Merge pull request #142 from shon/master
Browse files Browse the repository at this point in the history
need_passwd option for user_check
  • Loading branch information
Sébastien Pierre committed Mar 26, 2013
2 parents de64f7d + 07c15de commit fbe82a5
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 29 deletions.
26 changes: 15 additions & 11 deletions src/cuisine.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,7 @@ def python_package_ensure_pip(package=None, r=None, pip=None):
path to a virtualenv. If provided, it will be added to the pip call.
'''
#FIXME: At the moment, I do not know how to check for the existence of a pip package and
# I am not sure if this really makes sense, based on the pip built in functionality.
# I am not sure if this really makes sense, based on the pip built in functionality.
# So I just call the install functions
pip=pip or fabric.api.env.get('pip','pip')
python_package_install_pip(package,r,pip)
Expand All @@ -908,7 +908,7 @@ def python_package_remove_pip(package, E=None, pip=None):
is equivalent to the "-r" parameter of pip.
Either "package" or "r" needs to be provided
The optional argument "E" is equivalent to the "-E" parameter of pip. E is the
path to a virtualenv. If provided, it will be added to the pip call.
path to a virtualenv. If provided, it will be added to the pip call.
'''
pip=pip or fabric.api.env.get('pip','pip')
return run('%s uninstall %s' %(pip,package))
Expand All @@ -934,7 +934,7 @@ def python_package_ensure_easy_install(package):
The "package" argument, defines the name of the package that will be ensured.
'''
#FIXME: At the moment, I do not know how to check for the existence of a py package and
# I am not sure if this really makes sense, based on the easy_install built in functionality.
# I am not sure if this really makes sense, based on the easy_install built in functionality.
# So I just call the install functions
python_package_install_easy_install(package)

Expand All @@ -943,7 +943,7 @@ def python_package_remove_easy_install(package):
The "package" argument, defines the name of the package that will be removed.
'''
#FIXME: this will not remove egg file etc.
run('easy_install -m %s' %package)
run('easy_install -m %s' %package)

# =============================================================================
#
Expand Down Expand Up @@ -1007,25 +1007,29 @@ def user_create(name, passwd=None, home=None, uid=None, gid=None, shell=None,
if passwd:
user_passwd(name=name,passwd=passwd,encrypted_passwd=encrypted_passwd)

def user_check(name=None, uid=None):
def user_check(name=None, uid=None, need_passwd=True):
"""Checks if there is a user defined with the given name,
returning its information as a
'{"name":<str>,"uid":<str>,"gid":<str>,"home":<str>,"shell":<str>}'
or 'None' if the user does not exists."""
or 'None' if the user does not exists.
need_passwd (Boolean) indicates if password to be included in result or not.
If set to True it parses /etc/shadow and needs sudo access
"""
assert name!=None or uid!=None, "user_check: either `uid` or `name` should be given"
assert name is None or uid is None,"user_check: `uid` and `name` both given, only one should be provided"
if name != None:
d = sudo("cat /etc/passwd | egrep '^%s:' ; true" % (name))
d = run("cat /etc/passwd | egrep '^%s:' ; true" % (name))
elif uid != None:
d = sudo("cat /etc/passwd | egrep '^.*:.*:%s:' ; true" % (uid))
d = run("cat /etc/passwd | egrep '^.*:.*:%s:' ; true" % (uid))
results = {}
s = None
if d:
d = d.split(":")
assert len(d) >= 7, "/etc/passwd entry is expected to have at least 7 fields, got %s in: %s" % (len(d), ":".join(d))
results = dict(name=d[0], uid=d[2], gid=d[3], fullname=d[4], home=d[5], shell=d[6])
s = sudo("cat /etc/shadow | egrep '^%s:' | awk -F':' '{print $2}'" % (results['name']))
if s: results['passwd'] = s
if need_passwd:
s = sudo("cat /etc/shadow | egrep '^%s:' | awk -F':' '{print $2}'" % (results['name']))
if s: results['passwd'] = s
if results:
return results
else:
Expand Down Expand Up @@ -1152,7 +1156,7 @@ def ssh_keygen(user, keytype="dsa"):
def ssh_authorize(user, key):
"""Adds the given key to the '.ssh/authorized_keys' for the given
user."""
d = user_check(user)
d = user_check(user, need_passwd=False)
group = d["gid"]
keyf = d["home"] + "/.ssh/authorized_keys"
if key[-1] != "\n":
Expand Down
47 changes: 29 additions & 18 deletions tests/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ def testUserCheck( self ):
assert cuisine.user_check(uid=user_data["uid"])
assert cuisine.user_check(uid=user_data["uid"])["name"] == user_data["name"]

def testUserCheckNeedPasswd( self ):
user_data = cuisine.user_check(USER, need_passwd=False)
user_data_with_passwd = cuisine.user_check(name=USER)
assert user_data
assert user_data["name"] == USER
assert 'passwd' in user_data_with_passwd
assert 'passwd' not in user_data
# We ensure that user_check works with uid and name
assert cuisine.user_check(uid=user_data["uid"], need_passwd=False)
assert cuisine.user_check(uid=user_data["uid"], need_passwd=False)["name"] == user_data["name"]

class Modes(unittest.TestCase):

def testModeLocal( self ):
Expand Down Expand Up @@ -63,7 +74,7 @@ def testModeSudo( self ):
# with cd(tmpdir), cuisine.mode_sudo():
# cuisine.run('echo "test" > test.txt')
# cuisine.run('chmod 0600 test.txt')
#
#
# with cd(tmpdir), cuisine.mode_user(), settings(warn_only=True):
# listing = cuisine.run('ls -la test.txt').split()
# self.assertEqual('root', listing[2]) # user
Expand All @@ -76,7 +87,7 @@ def testModeSudo( self ):

# NOTE: Test disabled for now
# class LocalExecution(unittest.TestCase):
#
#
# def testFabricLocalCommands( self ):
# '''
# Make sure local and lcd still work properly and that run and cd
Expand All @@ -87,31 +98,31 @@ def testModeSudo( self ):
# dir1 = os.path.join(tmpdir, 'test1')
# dir2 = os.path.join(tmpdir, 'test2')
# [os.mkdir(d) for d in [dir1, dir2]]
#
#
# with cd(dir1), fabric.api.lcd(dir2):
# file1 = os.path.join(dir1, 'test1.txt')
# cuisine.run('touch %s' % file1)
#
#
# file2 = os.path.join(dir2, 'test2.txt')
# fabric.api.local('touch %s' % file2)
#
#
# self.assertTrue(cuisine.file_exists(file2))
# finally:
# shutil.rmtree(tmpdir)
#
#
#
#
# def testResultAttributes( self ):
# failing_command = 'cat /etc/shadow' # insufficient permissions
# succeeding_command = 'uname -a'
# erroneous_command = 'this-command-does-not-exist -a'
#
#
# # A successful command should have the appropriate status
# # attributes set
# result = cuisine.run(succeeding_command)
# self.assertTrue(result.succeeded)
# self.assertFalse(result.failed)
# self.assertEqual(result.return_code, 0)
#
#
# # With warn_only set, we should be able to examine the result
# # even if it fails
# with settings(warn_only=True):
Expand All @@ -122,29 +133,29 @@ def testModeSudo( self ):
# self.assertEqual(result.return_code, 1)
# self.assertIsNotNone(result.stderr)
# self.assertIn('Permission denied', result.stderr)
#
#
# # With warn_only off, failure should cause execution to abort
# with settings(warn_only=False):
# with self.assertRaises(SystemExit):
# cuisine.run(failing_command)
#
#
# # An erroneoneous command should fail similarly to fabric
# with settings(warn_only=True):
# result = cuisine.run(erroneous_command)
# self.assertTrue(result.failed)
# self.assertEqual(result.return_code, 127)
#
#
# def testCd( self ):
# with cd('/tmp'):
# self.assertEqual(cuisine.run('pwd'), '/tmp')
#
#
# def testShell( self ):
# # Ensure that env.shell is respected by setting it to the
# # Ensure that env.shell is respected by setting it to the
# # 'exit' command and testing that it aborts.
# with settings(use_shell=True, shell='exit'):
# with self.assertRaises(SystemExit):
# cuisine.run('ls')
#
#
# def testSudoPrefix( self ):
# # Ensure that env.sudo_prefix is respected by setting it to
# # echo the command to stdout rather than executing it
Expand All @@ -155,12 +166,12 @@ def testModeSudo( self ):
# self.assertNotEqual(run_result.stdout, sudo_result.stdout)
# self.assertIn(env.shell, sudo_result)
# self.assertIn(cmd, sudo_result)
#
#
# def testPath( self ):
# # Make sure the path is applied properly by setting it empty
# # Make sure the path is applied properly by setting it empty
# # and making sure that stops a simple command from running
# self.assertTrue(cuisine.run('ls').succeeded)
#
#
# with fabric.api.path(' ', behavior='replace'), settings(warn_only=True):
# result = cuisine.run('ls', combine_stderr=False)
# self.assertTrue(result.failed)
Expand Down

0 comments on commit fbe82a5

Please sign in to comment.