From cf67667e67e282a37f1b81e291a7a395d96ac896 Mon Sep 17 00:00:00 2001 From: Larry Hamel Date: Wed, 28 Jun 2017 10:29:52 -0700 Subject: [PATCH] Refactor to introduce a main method Also, added a unit test. Signed-off-by: Nadeem Ghani --- .../bin/gppylib/test/unit/test_unit_gpssh.py | 41 +++++++ gpMgmt/bin/gpssh | 106 +++++++++--------- 2 files changed, 96 insertions(+), 51 deletions(-) create mode 100644 gpMgmt/bin/gppylib/test/unit/test_unit_gpssh.py diff --git a/gpMgmt/bin/gppylib/test/unit/test_unit_gpssh.py b/gpMgmt/bin/gppylib/test/unit/test_unit_gpssh.py new file mode 100644 index 0000000000..d2b5920b2c --- /dev/null +++ b/gpMgmt/bin/gppylib/test/unit/test_unit_gpssh.py @@ -0,0 +1,41 @@ +import imp +import os +import io + +import sys +from mock import patch + +from gp_unittest import GpTestCase + + +class GpSshTestCase(GpTestCase): + + def setUp(self): + # because gpssh does not have a .py extension, we have to use imp to import it + # if we had a gpssh.py, this is equivalent to: + # import gpssh + # self.subject = gpssh + gpssh_file = os.path.abspath(os.path.dirname(__file__) + "/../../../gpssh") + self.subject = imp.load_source('gpssh', gpssh_file) + + @patch('sys.exit') + def test_when_run_without_args_prints_help_text(self, mock): + mock.side_effect = Exception("on purpose") + # GOOD_MOCK_EXAMPLE of stdout + with patch('sys.stdout', new=io.BytesIO()) as mock_stdout: + with self.assertRaisesRegexp(Exception, "on purpose"): + self.subject.main() + # assert on what main() was expected to do + # in this case, check what was written to sys.stdout? + self.assertIn('gpssh -- ssh access to multiple hosts at once', mock_stdout.getvalue()) + + def test_when_remote_host_cpu_load_causes_bad_prompts_will_retry_and_succeed(self): + pass + # sys.argv = ['', '-h', 'localhost', 'uptime'] + # self.subject.main() + # assert on what main() was expected to do + # in this case, check what was written to sys.stdout? + + def test_when_remote_host_cpu_load_causes_bad_prompts_will_retry_and_fail(self): + pass + diff --git a/gpMgmt/bin/gpssh b/gpMgmt/bin/gpssh index 89d257e773..ab6001c40a 100755 --- a/gpMgmt/bin/gpssh +++ b/gpMgmt/bin/gpssh @@ -19,14 +19,9 @@ Usage: gpssh [--version] [-?v] [-h host] [-f hostfile] [cmd] import os import sys -progname = os.path.split(sys.argv[0])[-1] +# todo is this necessary? sys.path.insert(1, sys.path[0] + '/lib') -if sys.version_info < (2, 5, 0): - sys.exit( -'''Error: %s is supported on Python versions 2.5 or greater -Please upgrade python installed on this machine.''' % progname) - import getopt import atexit import signal @@ -69,13 +64,11 @@ def usage(exitarg): sys.exit(exitarg) -############# def print_version(): print '%s version $Revision$' % GV.script_name sys.exit(0) -############# def parseCommandLine(): try: (options, args) = getopt.getopt(sys.argv[1:], '?evsh:f:D:u:d:t:', ['version']) @@ -224,52 +217,63 @@ def interactive(): pass -try: - # Parse options from the command line - parseCommandLine() - - # Parse gpssh.conf file - parseConfigFile() - - # Acquire the list of hosts from command line arguments - hostlist = ssh_utils.HostList() - for h in GV.opt['-h']: - hostlist.add(h) - if GV.opt['-f']: - hostlist.parseFile(GV.opt['-f']) +def main(): + if sys.version_info < (2, 5, 0): + sys.exit( + '''Error: %s is supported on Python versions 2.5 or greater + Please upgrade python installed on this machine.''' % os.path.split(sys.argv[0])[-1]) - # Filter out non-unique hostnames unless the -D option is provided - if not GV.opt['-D']: - GV.opt['-h'] = hostlist.filterMultiHomedHosts() - else: - GV.opt['-h'] = hostlist.get() + try: + # Parse options from the command line + parseCommandLine() + + # Parse gpssh.conf file + parseConfigFile() + + # Acquire the list of hosts from command line arguments + hostlist = ssh_utils.HostList() + for h in GV.opt['-h']: + hostlist.add(h) + if GV.opt['-f']: + hostlist.parseFile(GV.opt['-f']) + + # Filter out non-unique hostnames unless the -D option is provided + if not GV.opt['-D']: + GV.opt['-h'] = hostlist.filterMultiHomedHosts() + else: + GV.opt['-h'] = hostlist.get() + + if len(GV.opt['-h']) == 0: + usage('Error: missing hosts in -h and/or -f arguments') + + # If a single command was passed to us, implement a single command session + if GV.argcmd: + try: + GV.session = ssh_utils.Session() + GV.session.verbose = GV.opt['-v'] + GV.session.login(GV.opt['-h'], GV.USER, GV.DELAY_BEFORE_SEND, GV.PROMPT_VALIDATION_TIMEOUT) + GV.session.echoCommand = GV.opt['-e'] + if GV.opt['-s']: + GV.session.executeCommand("source {0}/greenplum_path.sh".format(os.environ["GPHOME"])) + output = GV.session.executeCommand(GV.argcmd) + GV.session.writeCommandOutput(output) + if GV.session.verbose: print '[INFO] completed successfully' + sys.stdout.flush() + except ssh_utils.Session.SessionError, e: + print 'Error: %s' % e + pass - if len(GV.opt['-h']) == 0: - usage('Error: missing hosts in -h and/or -f arguments') + else: # Otherwise, implement an interactive session + interactive() - # If a single command was passed to us, implement a single command session - if GV.argcmd: - try: - GV.session = ssh_utils.Session() - GV.session.verbose = GV.opt['-v'] - GV.session.login(GV.opt['-h'], GV.USER, GV.DELAY_BEFORE_SEND, GV.PROMPT_VALIDATION_TIMEOUT) - GV.session.echoCommand = GV.opt['-e'] - if GV.opt['-s']: - GV.session.executeCommand("source {0}/greenplum_path.sh".format(os.environ["GPHOME"])) - output = GV.session.executeCommand(GV.argcmd) - GV.session.writeCommandOutput(output) - if GV.session.verbose: print '[INFO] completed successfully' - sys.stdout.flush() - except ssh_utils.Session.SessionError, e: - print 'Error: %s' % e - pass + return_code = sessionCleanup() + sys.exit(return_code) - else: # Otherwise, implement an interactive session - interactive() + except KeyboardInterrupt: + sessionCleanup() + sys.exit('\nInterrupted...') - return_code = sessionCleanup() - sys.exit(return_code) -except KeyboardInterrupt: - sessionCleanup() - sys.exit('\nInterrupted...') +############# +if __name__ == '__main__': + main() -- GitLab