You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2013/01/28 05:15:45 UTC
svn commit: r1439248 - in /libcloud/branches/0.12.x: ./ CHANGES
libcloud/compute/ssh.py libcloud/test/compute/test_ssh_client.py setup.py
tox.ini
Author: tomaz
Date: Mon Jan 28 04:15:44 2013
New Revision: 1439248
URL: http://svn.apache.org/viewvc?rev=1439248&view=rev
Log:
Backport commits from r1439233:r1439246 from trunk:
Fix the ScriptDeployment step to work correctly if user provides a relative path
for the script argument.
Contributed by Jaume devesa, part of LIBCLOUD-278.
Modified:
libcloud/branches/0.12.x/ (props changed)
libcloud/branches/0.12.x/CHANGES
libcloud/branches/0.12.x/libcloud/compute/ssh.py
libcloud/branches/0.12.x/libcloud/test/compute/test_ssh_client.py
libcloud/branches/0.12.x/setup.py
libcloud/branches/0.12.x/tox.ini
Propchange: libcloud/branches/0.12.x/
------------------------------------------------------------------------------
Merged /libcloud/trunk:r1439233-1439247
Modified: libcloud/branches/0.12.x/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/branches/0.12.x/CHANGES?rev=1439248&r1=1439247&r2=1439248&view=diff
==============================================================================
--- libcloud/branches/0.12.x/CHANGES (original)
+++ libcloud/branches/0.12.x/CHANGES Mon Jan 28 04:15:44 2013
@@ -98,6 +98,13 @@ Changes with Apache Libcloud 0.12.0:
'create_node' method. (LIBCLOUD-282)
[Joe Miller, Tomaz Muraus]
+ - Improve error handling in the Brightbox driver.
+ [Tomaz Muraus]
+
+ - Fix the ScriptDeployment step to work correctly if user provides a
+ relative path for the script argument. (LIBCLOUD-278)
+ [Jaume Devesa]
+
*) Storage
- Add a new local storage driver.
@@ -127,9 +134,6 @@ Changes with Apache Libcloud 0.12.0:
(LIBCLOUD-269)
[Mahendra M]
- - Improve error handling in the Brightbox driver.
- [Tomaz Muraus]
-
*) DNS
- Update 'if type' checks in the update_record methods to behave correctly
Modified: libcloud/branches/0.12.x/libcloud/compute/ssh.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.12.x/libcloud/compute/ssh.py?rev=1439248&r1=1439247&r2=1439248&view=diff
==============================================================================
--- libcloud/branches/0.12.x/libcloud/compute/ssh.py (original)
+++ libcloud/branches/0.12.x/libcloud/compute/ssh.py Mon Jan 28 04:15:44 2013
@@ -29,6 +29,7 @@ except ImportError:
# Ref: https://bugs.launchpad.net/paramiko/+bug/392973
from os.path import split as psplit
+from os.path import join as pjoin
class BaseSSHClient(object):
@@ -120,6 +121,7 @@ class BaseSSHClient(object):
class ParamikoSSHClient(BaseSSHClient):
+
"""
A SSH Client powered by Paramiko.
"""
@@ -179,6 +181,19 @@ class ParamikoSSHClient(BaseSSHClient):
sftp.close()
def run(self, cmd):
+ if cmd[0] != '/':
+ # If 'cmd' based on relative path,
+ # set the absoute path joining the HOME path
+ sftp = self.client.open_sftp()
+ # Chdir to its own directory is mandatory because otherwise
+ # the 'getcwd()' method returns None
+ sftp.chdir('.')
+ cwd = sftp.getcwd()
+ sftp.close()
+
+ # Join the command to the current path
+ cmd = pjoin(cwd, cmd)
+
# based on exec_command()
bufsize = -1
t = self.client.get_transport()
Modified: libcloud/branches/0.12.x/libcloud/test/compute/test_ssh_client.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.12.x/libcloud/test/compute/test_ssh_client.py?rev=1439248&r1=1439247&r2=1439248&view=diff
==============================================================================
--- libcloud/branches/0.12.x/libcloud/test/compute/test_ssh_client.py (original)
+++ libcloud/branches/0.12.x/libcloud/test/compute/test_ssh_client.py Mon Jan 28 04:15:44 2013
@@ -17,13 +17,156 @@
import sys
import unittest
-import libcloud.compute.ssh
+from libcloud.compute.ssh import ParamikoSSHClient
+from libcloud.compute.ssh import have_paramiko
-from mock import Mock
+from mock import patch, Mock
+
+if not have_paramiko:
+ ParamikoSSHClient = None
class ParamikoSSHClientTests(unittest.TestCase):
- pass
+ @patch('paramiko.SSHClient', Mock)
+ def setUp(self):
+ """
+ Creates the object patching the actual connection.
+ """
+ conn_params = {'hostname': 'dummy.host.org',
+ 'port': 8822,
+ 'username': 'ubuntu',
+ 'key': '~/.ssh/ubuntu_ssh',
+ 'timeout': '600'}
+ self.ssh_cli = ParamikoSSHClient(**conn_params)
+
+ @patch('paramiko.SSHClient', Mock)
+ def test_create_with_password(self):
+ """
+ Initialize object with password.
+
+ Just to have better coverage, initialize the object
+ with the 'password' value instead of the 'key'.
+ """
+ conn_params = {'hostname': 'dummy.host.org',
+ 'username': 'ubuntu',
+ 'password': 'ubuntu'}
+ mock = ParamikoSSHClient(**conn_params)
+ mock.connect()
+
+ expected_conn = {'username': 'ubuntu',
+ 'password': 'ubuntu',
+ 'allow_agent': False,
+ 'hostname': 'dummy.host.org',
+ 'look_for_keys': False,
+ 'port': 22}
+ mock.client.connect.assert_called_once_with(**expected_conn)
+
+ @patch('paramiko.SSHClient', Mock)
+ def test_create_without_credentials(self):
+ """
+ Initialize object with no credentials.
+
+ Just to have better coverage, initialize the object
+ without 'password' neither 'key'.
+ """
+ conn_params = {'hostname': 'dummy.host.org',
+ 'username': 'ubuntu'}
+ mock = ParamikoSSHClient(**conn_params)
+ mock.connect()
+
+ expected_conn = {'username': 'ubuntu',
+ 'hostname': 'dummy.host.org',
+ 'allow_agent': True,
+ 'look_for_keys': True,
+ 'port': 22}
+ mock.client.connect.assert_called_once_with(**expected_conn)
+
+ def test_basic_usage_absolute_path(self):
+ """
+ Basic execution.
+ """
+ mock = self.ssh_cli
+ # script to execute
+ sd = "/root/random_script.sh"
+
+ # Connect behavior
+ mock.connect()
+ mock_cli = mock.client # The actual mocked object: SSHClient
+ expected_conn = {'username': 'ubuntu',
+ 'key_filename': '~/.ssh/ubuntu_ssh',
+ 'allow_agent': False,
+ 'hostname': 'dummy.host.org',
+ 'look_for_keys': False,
+ 'timeout': '600',
+ 'port': 8822}
+ mock_cli.connect.assert_called_once_with(**expected_conn)
+
+ mock.put(sd)
+ # Make assertions over 'put' method
+ mock_cli.open_sftp().chdir.assert_called_with('root')
+ mock_cli.open_sftp().file.assert_called_once_with('random_script.sh',
+ mode='w')
+
+ mock.run(sd)
+ # Make assertions over 'run' method
+ mock_cli.get_transport().open_session().exec_command \
+ .assert_called_once_with(sd)
+
+ mock.close()
+
+ def test_run_script_with_relative_path(self):
+ """
+ Execute script with relative path.
+ """
+ mock = self.ssh_cli
+
+ # Define behaviour then ask for 'current directory'
+ mock.client.open_sftp().getcwd.return_value = '/home/ubuntu/'
+
+ # Script without full path
+ sd = 'random_script.sh'
+
+ # Without assertions because they are the same than the previous
+ # 'test_basic_usage' method
+ mock.connect()
+
+ mock_cli = mock.client # The actual mocked object: SSHClient
+
+ mock.put(sd, chmod=600)
+ # Make assertions over 'put' method
+ mock_cli.open_sftp().file.assert_called_once_with('random_script.sh',
+ mode='w')
+ mock_cli.open_sftp().file().chmod.assert_called_once_with(600)
+
+ mock.run(sd)
+ # Make assertions over the 'run' method
+ mock_cli.open_sftp().chdir.assert_called_with(".")
+ mock_cli.open_sftp().getcwd.assert_called_once()
+ full_sd = '/home/ubuntu/random_script.sh'
+ mock_cli.get_transport().open_session().exec_command \
+ .assert_called_once_with(full_sd)
+
+ mock.close()
+
+ def test_delete_script(self):
+ """
+ Provide a basic test with 'delete' action.
+ """
+ mock = self.ssh_cli
+ # script to execute
+ sd = '/root/random_script.sh'
+
+ mock.connect()
+
+ mock.delete(sd)
+ # Make assertions over the 'delete' method
+ mock.client.open_sftp().unlink.assert_called_with(sd)
+
+ mock.close()
+
+if not ParamikoSSHClient:
+ class ParamikoSSHClientTests(unittest.TestCase):
+ pass
if __name__ == '__main__':
Modified: libcloud/branches/0.12.x/setup.py
URL: http://svn.apache.org/viewvc/libcloud/branches/0.12.x/setup.py?rev=1439248&r1=1439247&r2=1439248&view=diff
==============================================================================
--- libcloud/branches/0.12.x/setup.py (original)
+++ libcloud/branches/0.12.x/setup.py Mon Jan 28 04:15:44 2013
@@ -51,6 +51,9 @@ if sys.version_info <= (2, 4):
', '.join(SUPPORTED_VERSIONS))
sys.exit(1)
+# pre-2.6 will need the ssl PyPI package
+pre_python26 = (sys.version_info[0] == 2 and sys.version_info[1] < 6)
+
def read_version_string():
version = None
@@ -106,8 +109,6 @@ class TestCommand(Command):
print("Please copy the new secret.py-dist file over otherwise" +
" tests might fail")
- pre_python26 = (sys.version_info[0] == 2
- and sys.version_info[1] < 6)
if pre_python26:
missing = []
# test for dependencies
@@ -130,6 +131,9 @@ class TestCommand(Command):
testfiles = []
for test_path in TEST_PATHS:
for t in glob(pjoin(self._dir, test_path, 'test_*.py')):
+ if pre_python26 and 'test_ssh_client' in t:
+ # TODO: Need to update mock library on buildslave
+ continue
testfiles.append('.'.join(
[test_path.replace('/', '.'), splitext(basename(t))[0]]))
@@ -215,8 +219,6 @@ class CoverageCommand(Command):
cov.save()
cov.html_report()
-# pre-2.6 will need the ssl PyPI package
-pre_python26 = (sys.version_info[0] == 2 and sys.version_info[1] < 6)
setup(
name='apache-libcloud',
Modified: libcloud/branches/0.12.x/tox.ini
URL: http://svn.apache.org/viewvc/libcloud/branches/0.12.x/tox.ini?rev=1439248&r1=1439247&r2=1439248&view=diff
==============================================================================
--- libcloud/branches/0.12.x/tox.ini (original)
+++ libcloud/branches/0.12.x/tox.ini Mon Jan 28 04:15:44 2013
@@ -5,6 +5,7 @@ envlist = py25,py26,py27,pypy,py32,py33
[testenv]
deps = mock
lockfile
+ paramiko
commands = python setup.py test
[testenv:py25]
@@ -12,6 +13,7 @@ deps = mock
lockfile
ssl
simplejson
+ paramiko
[testenv:py32]
deps = mock