@@ -31,11 +31,15 @@ def configure(self, parser):
3131 parser .add_argument ('--noscb' , action = 'store_false' , dest = 'use_scb' ,
3232 help = 'Disable use of Shell Control Box (SCB) '
3333 'even if it is enabled in the cluster config' )
34+ parser .add_argument (
35+ '--teleport' ,
36+ action = 'store_false' ,
37+ dest = 'use_teleport' ,
38+ help = 'Use Teleport for SSH' )
3439 parser .add_argument (
3540 'opts' ,
36- default = ['-va --progress' ],
3741 nargs = '*' ,
38- help = 'Rsync opts' )
42+ help = 'Sync opts' )
3943
4044 def get_help (self ):
4145 return 'Sync files from/to a cluster'
@@ -54,6 +58,9 @@ def get_epilog(self):
5458
5559 # extra rsync options
5660 ops cluster.yml sync 'dcs[0]:/usr/local/demdex/conf' /tmp/configurator-data -l remote_user -- --progress
61+
62+ # extra sync option for Teleport (recursive download, quiet, port)
63+ ops cluster.yml sync 'dcs[0]:/usr/local/demdex/conf' /tmp/configurator-data -- --recursive/port/quiet
5764 """
5865
5966
@@ -73,29 +80,36 @@ def __init__(self, cluster_config, root_dir,
7380
7481 def run (self , args , extra_args ):
7582 logger .info ("Found extra_args %s" , extra_args )
76- inventory_path , ssh_config_paths = self . inventory_generator . generate ()
83+
7784 src = PathExpr (args .src )
7885 dest = PathExpr (args .dest )
86+ remote = self .get_remote (dest , src )
7987
80- ssh_config_path = SshConfigGenerator .get_ssh_config_path (self .cluster_config ,
81- ssh_config_paths ,
82- args .use_scb )
8388 if src .is_remote and dest .is_remote :
8489 display (
85- 'Too remote expressions are not allowed' ,
90+ 'Two remote expressions are not allowed' ,
8691 stderr = True ,
8792 color = 'red' )
8893 return
8994
90- if src .is_remote :
91- remote = src
92- else :
93- remote = dest
94-
9595 display (
9696 "Looking for hosts for pattern '%s'" %
9797 remote .pattern , stderr = True )
9898
99+ if self .is_teleport_enabled (args ):
100+ command = self .execute_teleport_scp (args , src , dest )
101+ else :
102+ ssh_user = self .cluster_config .get ('ssh_user' ) or self .ops_config .get ('ssh.user' ) or getpass .getuser ()
103+ if remote .remote_user :
104+ ssh_user = remote .remote_user
105+ elif args .user :
106+ ssh_user = args .user
107+ ssh_host = self .populate_remote_hosts (remote )[0 ]
108+ command = self .execute_rsync_scp (args , src , dest , ssh_user , ssh_host , self .get_ssh_config_path (args ))
109+
110+ return dict (command = command )
111+
112+ def populate_remote_hosts (self , remote ):
99113 remote_hosts = []
100114 hosts = self .ansible_inventory .get_hosts (remote .pattern )
101115 if not hosts :
@@ -106,28 +120,43 @@ def run(self, args, extra_args):
106120 for host in hosts :
107121 ssh_host = host .get_vars ().get ('ansible_ssh_host' ) or host
108122 remote_hosts .append (ssh_host )
123+ return remote_hosts
109124
110- for ssh_host in remote_hosts :
111- ssh_user = self .cluster_config .get ('ssh_user' ) or self .ops_config .get (
112- 'ssh.user' ) or getpass .getuser ()
113- if remote .remote_user :
114- ssh_user = remote .remote_user
115- elif args .user :
116- ssh_user = args .user
117-
118- from_path = src .with_user_and_path (ssh_user , ssh_host )
119- to_path = dest .with_user_and_path (ssh_user , ssh_host )
120-
121- command = 'rsync {opts} {from_path} {to_path} -e "ssh -F {ssh_config}"' .format (
122- opts = " " .join (args .opts ),
123- from_path = from_path ,
124- to_path = to_path ,
125- ssh_config = ssh_config_path
126-
127- )
128-
129- return dict (command = command )
130-
125+ def get_remote (self , dest , src ):
126+ if src .is_remote :
127+ remote = src
128+ else :
129+ remote = dest
130+ return remote
131+
132+ def get_ssh_config_path (self , args ):
133+ ssh_config_generator = SshConfigGenerator (self .ops_config .package_dir )
134+ _ , ssh_config_paths = self .inventory_generator .generate ()
135+ return ssh_config_generator .get_ssh_config_path (self .cluster_config ,
136+ ssh_config_paths ,
137+
138+ args )
139+
140+ def execute_teleport_scp (self , args , src , dest ):
141+ return 'tsh scp {opts} {from_path} {to_path}' .format (
142+ from_path = src ,
143+ to_path = dest ,
144+ opts = " " .join (args .opts )
145+ )
146+
147+ def execute_rsync_scp (self , args , src , dest , ssh_user , ssh_host , ssh_config_path ):
148+ from_path = src .with_user_and_path (ssh_user , ssh_host )
149+ to_path = dest .with_user_and_path (ssh_user , ssh_host )
150+ return 'rsync {opts} {from_path} {to_path} -e "ssh -F {ssh_config}"' .format (
151+ opts = " " .join (args .opts ),
152+ from_path = from_path ,
153+ to_path = to_path ,
154+ ssh_config = ssh_config_path
155+ )
156+
157+
158+ def is_teleport_enabled (self , args ):
159+ return True if self .cluster_config .get ('teleport' , {}).get ('enabled' ) and args .use_teleport else False
131160
132161class PathExpr (object ):
133162
0 commit comments