PK!tronald/__init__.py__version__ = "0.1.0" PK! ZZtronald/__main__.pytry: from tronald import cli except ImportError: from . import cli cli.run_cli() PK!1Itronald/cli.pyimport click import shelve import inquirer from time import sleep from .config import Config, SHELVE_NAME from .controllers import RemoteController, LocalController from .initial import ( KEY_PATH_SETUP, DEFAULT_DATABASE_SETUP, CONTAINER_PREFIX, CONTAINER_SUFFIX, perform_initial_setup, ) @click.group() def cli(): pass @cli.command(name="settings") @click.option("--prefix", "prefix") @click.option("--suffix", "suffix") @click.option("--key", "key_path") @click.option("--db", "db_name") def set_prefix(prefix, suffix, key_path, db_name): with shelve.open(SHELVE_NAME) as settings: if not prefix and not suffix and not key_path and not db_name: click.echo("Current settings:\n") for key, value in settings.items(): click.echo("{}: {}".format(key, value)) if prefix: settings["prefix"] = prefix if suffix: settings["suffix"] = suffix if key_path: settings["key_path"] = key_path if db_name: settings["db_name"] = db_name @cli.command() @click.option("--container", "container") @click.option("--ssh-user", "ssh_user") @click.option("--postgres-user", "postgres_user") @click.argument("host") @click.argument("target") def dump(host, container, ssh_user, postgres_user, target): configuration_parameters = { "host": host, "ssh_user": ssh_user, "postgres_user": postgres_user, "container": container, "target": target, } config = Config(**configuration_parameters) controller = RemoteController(config) controller.dump_and_transfer() @cli.command(name="import") @click.argument("dump_path") @click.argument("container_identifier") @click.option("--postgres-user", "postgres_user") def import_dump(dump_path, container_identifier, postgres_user): configuration_parameters = { "dump_path": dump_path, "container_identifier": container_identifier, "postgres_user": postgres_user or "django", } controller = LocalController(**configuration_parameters) controller.import_dump() def run_cli(): perform_initial_setup() cli() if __name__ == "__main__": perform_initial_setup() cli() PK!wtronald/commands.pyimport os def build_postgres_dump(config): return "docker exec -t {} pg_dump {} -c -U {} > {}".format( config.container, config.db_name, config.postgres_user, config.dump_name ) def remove_remote_dump(config): return "rm {}".format(config.dump_name) def import_dump_to_local_container(dump_path, container_identifier, postgres_user): return os.system( "cat {} | docker exec -i {} psql -U {}".format( dump_path, container_identifier, postgres_user ) ) PK! 5tronald/config.pyimport os import shelve SHELVE_NAME = "{}/tronald.conf".format(os.path.dirname(__file__)) class Config: def __init__( self, host=None, container=None, ssh_user=None, postgres_user=None, dump_name=None, target=None, ): self.host = host self.container = container self.postgres_user = postgres_user self.ssh_user = ssh_user self.target = target with shelve.open(SHELVE_NAME) as settings: self.db_name = settings["db_name"] self.prefix = settings["prefix"] self.suffix = settings["suffix"] self.key_path = settings["key_path"] @property def postgres_user(self): return self._postgres_user or "postgres" @postgres_user.setter def postgres_user(self, user): self._postgres_user = user @property def ssh_user(self): return self._ssh_user or "root" @ssh_user.setter def ssh_user(self, user): self._ssh_user = user @property def container(self): if self._container: return self._container if not self.host: raise Exception( "No container name derivation possible because of missing host." ) if self.host: return "{}{}{}".format(self.prefix, self.host, self.suffix) @container.setter def container(self, container_name): self._container = container_name @property def database(self): return self.db_name or "app" @property def rsa_key(self): return self.key_path or "~/.ssh/id_rsa" @property def target(self): return self._target or "recent-dump.db" @target.setter def target(self, target_path): self._target = target_path @property def dump_name(self): return "dump-{}.db".format(self._container) PK!劔tronald/controllers.pyimport time import paramiko from .commands import ( build_postgres_dump, remove_remote_dump, import_dump_to_local_container, ) def get_channel(client): return client.get_transport().open_session() class RemoteController: def __init__(self, config): self.client = paramiko.SSHClient() self.config = config self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) def dump_and_transfer(self): self.client.connect( self.config.host, username=self.config.ssh_user, key_filename=self.config.key_path, ) channel = get_channel(self.client) channel.exec_command(build_postgres_dump(self.config)) while not channel.exit_status_ready(): time.sleep(0.5) sftp = self.client.open_sftp() sftp.get(self.config.dump_name, self.config.target) channel = get_channel(self.client) channel.exec_command(remove_remote_dump(self.config)) sftp.close() self.client.close() class LocalController: def __init__(self, dump_path, container_identifier, postgres_user): self.postgres_user = postgres_user self.dump_path = dump_path self.container = container_identifier def import_dump(self): configuration_parameters = { "dump_path": self.dump_path, "container_identifier": self.container, "postgres_user": self.postgres_user, } import_dump_to_local_container(**configuration_parameters) PK!-Y~~tronald/initial.pyimport shelve import inquirer from .config import SHELVE_NAME KEY_PATH_SETUP = [ inquirer.Text( "key_path", "Please enter the absolute path to your preferred RSA private key", default="~/.ssh/id_rsa", ) ] DEFAULT_DATABASE_SETUP = [ inquirer.Text( "db_name", "Please enter the default database name to pull dumps from.", default="app", ) ] CONTAINER_PREFIX = [ inquirer.Text( "prefix", "If there are common container prefixes, please provide them for container name derivation.", ) ] CONTAINER_SUFFIX = [ inquirer.Text( "suffix", "If there are common container suffixes, please provide them for container name derivation.", ) ] def perform_initial_setup(): with shelve.open(SHELVE_NAME) as settings: if not "key_path" in settings: answer = inquirer.prompt(KEY_PATH_SETUP) settings["key_path"] = answer["key_path"] if not "db_name" in settings: answer = inquirer.prompt(DEFAULT_DATABASE_SETUP) settings["db_name"] = answer["db_name"] if not "prefix" in settings: answer = inquirer.prompt(CONTAINER_PREFIX) settings["prefix"] = answer["prefix"] if not "suffix" in settings: answer = inquirer.prompt(CONTAINER_SUFFIX) settings["suffix"] = answer["suffix"] PK!Z+=[@@tronald/tronald.confϚW @ S0*db_n0 pref30 wkey_0X#suffC0 key_pathX ~/.ssh/id_rsaq.db_nameXappq.prefixXq.suffixXq.PK!HڽTUtronald-0.1.0.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!H7Q tronald-0.1.0.dist-info/METADATA[K@WBMmei`E>4K nzAoss1@t|,Fg }E=uZ%gVcBxlE%ø«uߐo*`O %vHgzamD:ruqri2)W -a|vv5]ewʏ{5 ylr1Y2?oNd?ScWdPK!HfK%tronald-0.1.0.dist-info/RECORDuv@}*,f ;O?9YdUꯪq\a4DѺy-Xw@jѶjҧ4