Implemented 'symlink' CLI command
Change-Id: I4d22328291fec99a8959624847ed09ee2272df35
diff --git a/setup.cfg b/setup.cfg
index 6bad8ba..5e63e23 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -52,6 +52,7 @@
trsync =
push = trsync.cmd.cli:PushCmd
+ symlink = trsync.cmd.cli:SymlinkCmd
remove = trsync.cmd.cli:RemoveCmd
[global]
diff --git a/trsync/cmd/cli.py b/trsync/cmd/cli.py
index 765cdc7..4b555ef 100644
--- a/trsync/cmd/cli.py
+++ b/trsync/cmd/cli.py
@@ -131,6 +131,89 @@
sys.exit(exitcode)
+class SymlinkCmd(command.Command):
+ log = logging.getLogger(__name__)
+
+ def get_description(self):
+ return "Create (or update) symlinks on remote"
+
+ def get_parser(self, prog_name):
+ parser = super(SymlinkCmd, self).get_parser(prog_name)
+ parser.add_argument('-d', '--dest',
+ nargs='+',
+ required=True,
+ help='Destination rsync url (local, rsyncd, '
+ 'remote shell).')
+ parser.add_argument('-t', '--target',
+ required=True,
+ help='All the symlinks will target to (relative '
+ 'symlink name). Url by default.')
+ parser.add_argument('-s', '--symlinks',
+ nargs='+',
+ required=True,
+ default=[],
+ help='Update specified symlinks (names relative '
+ 'dest).')
+ parser.add_argument('--update',
+ action='store_true',
+ required=False,
+ default=False,
+ help='It specified, all existent symlinks will be '
+ 'updated. Will be skiped otherwise. Disabled by '
+ 'default.')
+ parser.add_argument('--extra',
+ required=False,
+ default='',
+ help='String with additional rsync parameters. '
+ 'For example it may be "\--dry-run '
+ '--any-rsync-option".Use "\\" to disable '
+ 'argparse to parse extra value.')
+
+ return parser
+
+ def take_action(self, parsed_args):
+ properties = vars(parsed_args)
+ symlinks = properties.pop('symlinks', [])
+ for symlink in symlinks:
+ if symlink.startswith('/') or symlink.startswith('../'):
+ self.log.error('Symlink name outside the root url: %s',
+ symlink)
+ raise RuntimeError('Symlink name the root url: {}'
+ ''.format(symlink))
+ servers = properties.pop('dest', None)
+ target = properties.pop('target', None)
+ if properties['extra'].startswith('\\'):
+ properties['extra'] = properties['extra'][1:]
+ properties['rsync_extra_params'] = properties.pop('extra')
+ update = properties.pop('update', None)
+
+ report = dict()
+ exitcode = 0
+
+ for server in servers:
+ report[server] = dict()
+ try:
+ remote = rsync_ops.RsyncOps(server, **properties)
+ for symlink in symlinks:
+ remote.symlink(symlink, target, update=update)
+ report[server]['success'] = True
+ except Exception as e:
+ report[server]['success'] = False
+ report[server]['log'] = e.message
+ exitcode = 1
+
+ for srv, msg in report.items():
+ if msg['success']:
+ self.log.info('Creating symlinks %s targeted to %s on %s: '
+ 'SUCCESS' % (str(symlinks), target, srv))
+ else:
+ self.log.error('Creating symlinks %s targeted to %s on %s: '
+ 'FAILED' % (str(symlinks), target, srv))
+ self.log.error(msg['log'])
+
+ sys.exit(exitcode)
+
+
class RemoveCmd(command.Command):
log = logging.getLogger(__name__)