diff --git a/setup.py b/setup.py index abac764..c2547a4 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ setup( name='stormssh', - version='0.6.5', + version='0.6.6', packages=find_packages(), package_data={'storm': ['templates/*.html', 'static/css/*.css', 'static/css/themes/storm/*.css', 'static/css/themes/storm/img/*.png', diff --git a/storm/__init__.py b/storm/__init__.py index 0d240a0..81000d2 100644 --- a/storm/__init__.py +++ b/storm/__init__.py @@ -4,6 +4,7 @@ from operator import itemgetter import re +from shutil import copyfile from .parsers.ssh_config_parser import ConfigParser from .defaults import get_default @@ -36,8 +37,7 @@ def add_entry(self, name, host, user, port, id_file, custom_options=[]): return True - - def clone_entry(self, name, clone_name): + def clone_entry(self, name, clone_name, keep_original=True): host = self.is_host_in(name, return_match=True) if not host: raise ValueError(ERRORS["not_found"].format(name)) @@ -47,6 +47,8 @@ def clone_entry(self, name, clone_name): raise ValueError(ERRORS["already_in"].format(clone_name)) self.ssh_config.add_host(clone_name, host.get('options')) + if not keep_original: + self.ssh_config.delete_host(name) self.ssh_config.write_to_ssh_config() return True @@ -140,3 +142,6 @@ def is_host_in(self, host, return_match = False, regexp_match=False): if host_.get("host") == host or (regexp_match and re.match(host, host_.get("host"))): return True if not return_match else host_ return False if not return_match else None + + def backup(self, target_file): + return copyfile(self.ssh_config.ssh_config_file, target_file) \ No newline at end of file diff --git a/storm/__main__.py b/storm/__main__.py index 99b8de7..7528fe9 100644 --- a/storm/__main__.py +++ b/storm/__main__.py @@ -81,6 +81,33 @@ def clone(name, clone_name, config=None): except ValueError as error: print(get_formatted_message(error, 'error'), file=sys.stderr) +@command('move') +def move(name, entry_name, config=None): + """ + Move an entry to the sshconfig. + """ + storm_ = get_storm_instance(config) + + try: + + # validate name + if '@' in name: + raise ValueError('invalid value: "@" cannot be used in name.') + + storm_.clone_entry(name, entry_name, keep_original=False) + + print( + get_formatted_message( + '{0} moved in ssh config. you can ' + 'connect it by typing "ssh {0}".'.format( + entry_name + ), + 'success') + ) + + except ValueError as error: + print(get_formatted_message(error, 'error'), file=sys.stderr) + @command('edit') def edit(name, connection_uri, id_file="", o=[], config=None): @@ -234,6 +261,16 @@ def delete_all(config=None): except Exception as error: print(get_formatted_message(str(error), 'error'), file=sys.stderr) +@command('backup') +def backup(target_file, config=None): + """ + Backups the main ssh configuration into target file. + """ + storm_ = get_storm_instance(config) + try: + storm_.backup(target_file) + except Exception as error: + print(get_formatted_message(str(error), 'error'), file=sys.stderr) @command('web') @arg('port', nargs='?', default=9002, type=int) diff --git a/tests.py b/tests.py index c1bc05c..6f568f0 100644 --- a/tests.py +++ b/tests.py @@ -272,6 +272,12 @@ def test_search(self): self.assertTrue(out.startswith(b'Listing results for aws:')) self.assertIn(b'aws.apache', out) + def test_backup(self): + out, err, rc = self.run_cmd("backup /tmp/ssh_backup {0}".format( + self.config_arg)) + + self.assertEqual(True, os.path.exists("/tmp/ssh_backup")) + def test_invalid_search(self): out, err, rc = self.run_cmd("search THEREISNOTHINGRELATEDWITHME {0}".format(self.config_arg)) @@ -283,7 +289,6 @@ def test_delete_all(self): self.assertIn(b'all entries deleted', out) - def tearDown(self): os.unlink('/tmp/ssh_config_cli_tests') @@ -344,6 +349,35 @@ def test_clone_host(self): self.assertEqual(item.get("options").get("identityfile"), '/tmp/tmp.pub') self.assertEqual(item.get("options").get("user"), 'ops') + def test_move_host(self): + self.storm.add_entry('google', 'google.com', 'ops', '24', '/tmp/tmp.pub') + self.storm.clone_entry('google', 'yahoo', keep_original=False) + + has_yahoo = False + for item in self.storm.ssh_config.config_data: + if item.get("host") == 'yahoo': + has_yahoo = True + break + + has_google = False + for item in self.storm.ssh_config.config_data: + if item.get("host") == 'google': + has_google = True + break + + self.assertEqual(True, has_yahoo) + self.assertEqual(False, has_google) + self.assertEqual(item.get("options").get("port"), '24') + self.assertEqual(item.get("options").get("identityfile"), '/tmp/tmp.pub') + self.assertEqual(item.get("options").get("user"), 'ops') + + def test_backup(self): + self.storm.backup("/tmp/storm_ssh_config_backup_file") + self.assertEqual( + True, + os.path.exists("/tmp/storm_ssh_config_backup_file") + ) + def test_double_clone_exception(self): self.storm.add_entry('google', 'google.com', 'ops', '24', '/tmp/tmp.pub') self.storm.clone_entry('google', 'yahoo')