From 74308b26a5e2ac2366c5ac0d2b63110bd98d181f Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 9 Sep 2019 14:19:26 -0500 Subject: [PATCH] Add core `rsync()` function also `agent_sudo()` i guess, but that whole thing is decidedly less convenient now than it used to be. need to figure out a way to temporarily enable agent forwarding from within the fabric, if possible... --- rattail_fabric2/__init__.py | 5 ++--- rattail_fabric2/core.py | 40 +++++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/rattail_fabric2/__init__.py b/rattail_fabric2/__init__.py index 99fdb4c..c0bd1af 100644 --- a/rattail_fabric2/__init__.py +++ b/rattail_fabric2/__init__.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2018 Lance Edgar +# Copyright © 2010-2019 Lance Edgar # # This file is part of Rattail. # @@ -27,14 +27,13 @@ This package contains various tasks and associated functions for use with Fabric deployment and maintenance. """ -from __future__ import unicode_literals, absolute_import - from .core import ( get_debian_version, get_ubuntu_version, make_deploy, make_system_user, mkdir, + rsync, set_timezone, UNSPECIFIED, ) diff --git a/rattail_fabric2/core.py b/rattail_fabric2/core.py index bcfb895..bbd5705 100644 --- a/rattail_fabric2/core.py +++ b/rattail_fabric2/core.py @@ -24,20 +24,30 @@ Core Utilities """ -from __future__ import unicode_literals, absolute_import - import os import re import tempfile -import six - from mako.template import Template UNSPECIFIED = object() +def agent_sudo(c, cmd, user=None): + """ + Run a 'sudo' command on the target server, with full agent forwarding. + + .. note:: + For this to actually work, you must have enabled agent forwarding for + your actual connection to the target machine. This is perhaps most + easily accomplished via ``~/.ssh/config`` entries. It is assumed + however that you would only want to enable agent forwarding temporarily, + just long enough to e.g. rsync some files. + """ + c.sudo('SSH_AUTH_SOCK=$SSH_AUTH_SOCK {}'.format(cmd), user=user) + + def is_link(c, path, use_sudo=False): """ Return True if the given path is a symlink on the current remote host. @@ -79,7 +89,7 @@ def mkdir(c, paths, owner=None, mode=None, """ Recursively make one or more directories. """ - if isinstance(paths, six.string_types): + if isinstance(paths, str): paths = [paths] cmd = 'mkdir --parents {}'.format(' '.join(paths)) if use_sudo: @@ -163,12 +173,8 @@ def upload_mako_template(c, local_path, remote_path, context={}, temp_dir = tempfile.mkdtemp(prefix='rattail-fabric.') temp_path = os.path.join(temp_dir, os.path.basename(local_path)) text = template.render(**context) - if six.PY3: - with open(temp_path, 'wt', encoding=encoding) as f: - f.write(text) - else: - with open(temp_path, 'wb') as f: - f.write(text.encode(encoding)) + with open(temp_path, 'wt', encoding=encoding) as f: + f.write(text) os.chmod(temp_path, os.stat(local_path).st_mode) put(c, temp_path, remote_path, **kwargs) @@ -288,3 +294,15 @@ def make_deploy(deploy_path, last_segment='deploy'): |-- rattail.conf.template """ return Deployer(deploy_path, last_segment) + + +def rsync(c, host, *paths): + """ + Runs rsync as root, for the given host and file paths. + """ + for path in paths: + assert path.startswith('/') + path = path.rstrip('/') + # escape path for rsync + path = path.replace(' ', r'\\\ ').replace("'", r"\\\'") + agent_sudo(c, 'rsync -aP --del root@{0}:{1}/ {1}'.format(host, path))