libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From to...@apache.org
Subject svn commit: r1439234 - in /libcloud/trunk: CHANGES libcloud/compute/ssh.py libcloud/test/compute/test_ssh_client.py tox.ini
Date Mon, 28 Jan 2013 03:05:09 GMT
Author: tomaz
Date: Mon Jan 28 03:05:09 2013
New Revision: 1439234

URL: http://svn.apache.org/viewvc?rev=1439234&view=rev
Log:
Fix the ScriptDeployment step to work correctly if user provides a relative path
to the script.

Contributed by Jaume devesa, part of LIBCLOUD-278.

Modified:
    libcloud/trunk/CHANGES
    libcloud/trunk/libcloud/compute/ssh.py
    libcloud/trunk/libcloud/test/compute/test_ssh_client.py
    libcloud/trunk/tox.ini

Modified: libcloud/trunk/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1439234&r1=1439233&r2=1439234&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Mon Jan 28 03:05:09 2013
@@ -111,6 +111,10 @@ Changes with Apache Libcloud in developm
    - Improve error handling in the Brightbox driver.
      [Tomaz Muraus]
 
+   - Fix the ScriptDeployment step to work correctly if user provides a
+     relative path to the script. (LIBCLOUD-278)
+     [Jaume Devesa]
+
   *) Storage
 
     - Add a new local storage driver.

Modified: libcloud/trunk/libcloud/compute/ssh.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/ssh.py?rev=1439234&r1=1439233&r2=1439234&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/ssh.py (original)
+++ libcloud/trunk/libcloud/compute/ssh.py Mon Jan 28 03:05:09 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/trunk/libcloud/test/compute/test_ssh_client.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_ssh_client.py?rev=1439234&r1=1439233&r2=1439234&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_ssh_client.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_ssh_client.py Mon Jan 28 03:05:09 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/trunk/tox.ini
URL: http://svn.apache.org/viewvc/libcloud/trunk/tox.ini?rev=1439234&r1=1439233&r2=1439234&view=diff
==============================================================================
--- libcloud/trunk/tox.ini (original)
+++ libcloud/trunk/tox.ini Mon Jan 28 03:05:09 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



Mime
View raw message