sauce 0.12.2 → 0.12.3
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/support/sauce_connect +39 -30
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.12.
|
1
|
+
0.12.3
|
data/support/sauce_connect
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
from __future__ import with_statement
|
4
4
|
|
5
5
|
# TODO:
|
6
|
-
# * ?? Use "-o StrictHostKeyChecking no"
|
7
6
|
# * Move to REST API v1
|
8
7
|
# * windows: SSH link healthcheck (PuTTY session file hack?)
|
9
8
|
# * Daemonizing
|
@@ -11,7 +10,6 @@ from __future__ import with_statement
|
|
11
10
|
# * issue: unix: null file descriptors causes Expect script to fail
|
12
11
|
# * Renew tunnel lease (backend not implemented)
|
13
12
|
# * Check tunnel machine ports are open (backend not implemented)
|
14
|
-
#
|
15
13
|
|
16
14
|
import os
|
17
15
|
import sys
|
@@ -39,7 +37,7 @@ except ImportError:
|
|
39
37
|
import simplejson as json # Python 2.5 dependency
|
40
38
|
|
41
39
|
NAME = "sauce_connect"
|
42
|
-
RELEASE =
|
40
|
+
RELEASE = 21
|
43
41
|
DISPLAY_VERSION = "%s release %s" % (NAME, RELEASE)
|
44
42
|
PRODUCT_NAME = u"Sauce Connect"
|
45
43
|
VERSIONS_URL = "http://saucelabs.com/versions.json"
|
@@ -352,11 +350,13 @@ class ReverseSSHError(Exception):
|
|
352
350
|
|
353
351
|
class ReverseSSH(object):
|
354
352
|
|
355
|
-
def __init__(self, tunnel, host, ports, tunnel_ports,
|
353
|
+
def __init__(self, tunnel, host, ports, tunnel_ports,
|
354
|
+
use_ssh_config=False, debug=False):
|
356
355
|
self.tunnel = tunnel
|
357
356
|
self.host = host
|
358
357
|
self.ports = ports
|
359
358
|
self.tunnel_ports = tunnel_ports
|
359
|
+
self.use_ssh_config = use_ssh_config
|
360
360
|
self.debug = debug
|
361
361
|
|
362
362
|
self.proc = None
|
@@ -375,12 +375,8 @@ class ReverseSSH(object):
|
|
375
375
|
ssh_config_file = os.path.join(os.environ['HOME'], ".ssh", "config")
|
376
376
|
if os.path.exists(ssh_config_file):
|
377
377
|
logger.debug("Found %s" % ssh_config_file)
|
378
|
-
|
379
|
-
|
380
|
-
if os.path.exists(ssh_known_hosts):
|
381
|
-
if not os.path.isfile(ssh_known_hosts) or os.path.islink(ssh_known_hosts):
|
382
|
-
logger.debug("SSH known_hosts file (%s) is not a regular file "
|
383
|
-
% ssh_known_hosts)
|
378
|
+
if self.use_ssh_config:
|
379
|
+
logger.warn("Using local SSH config")
|
384
380
|
|
385
381
|
@property
|
386
382
|
def _dash_Rs(self):
|
@@ -390,27 +386,25 @@ class ReverseSSH(object):
|
|
390
386
|
return dash_Rs
|
391
387
|
|
392
388
|
def get_plink_command(self):
|
389
|
+
"""Return the Windows SSH command."""
|
393
390
|
verbosity = "-v" if self.debug else ""
|
394
391
|
return ("plink\plink %s -l %s -pw %s -N %s %s"
|
395
392
|
% (verbosity, self.tunnel.user, self.tunnel.password,
|
396
393
|
self._dash_Rs, self.tunnel.host))
|
397
394
|
|
398
395
|
def get_expect_script(self):
|
396
|
+
"""Return the Unix SSH command."""
|
399
397
|
wait = "wait"
|
400
398
|
if is_openbsd: # using 'wait;' hangs the script on OpenBSD
|
401
399
|
wait = "wait -nowait;sleep 1" # hack
|
402
400
|
|
403
401
|
verbosity = "-v" if self.debug else "-q"
|
402
|
+
config_file = "" if self.use_ssh_config else "-F /dev/null"
|
404
403
|
host_ip = socket.gethostbyname(self.tunnel.host)
|
405
404
|
script = (
|
406
|
-
"spawn ssh-
|
407
|
-
% (verbosity, self.tunnel.
|
408
|
-
|
409
|
-
"spawn ssh %s -p 22 -l %s -o ServerAliveInterval=%s -N %s %s;"
|
410
|
-
% (verbosity, self.tunnel.user, HEALTH_CHECK_INTERVAL,
|
411
|
-
self._dash_Rs, self.tunnel.host) +
|
412
|
-
'expect \\"Are you sure you want to continue connecting'
|
413
|
-
' (yes/no)?\\";send yes\\r;'
|
405
|
+
"spawn ssh %s %s -p 22 -l %s -o ServerAliveInterval=%s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -N %s %s;"
|
406
|
+
% (verbosity, config_file, self.tunnel.user,
|
407
|
+
HEALTH_CHECK_INTERVAL, self._dash_Rs, self.tunnel.host) +
|
414
408
|
"expect *password:;send -- %s\\r;" % self.tunnel.password +
|
415
409
|
"expect -timeout -1 timeout")
|
416
410
|
return script
|
@@ -539,7 +533,7 @@ def peace_out(tunnel=None, returncode=0, atexit=False):
|
|
539
533
|
logger.info("\ Exiting /")
|
540
534
|
raise SystemExit(returncode)
|
541
535
|
else:
|
542
|
-
logger.debug("
|
536
|
+
logger.debug("-- fin --")
|
543
537
|
|
544
538
|
|
545
539
|
def setup_signal_handler(tunnel, options):
|
@@ -632,7 +626,7 @@ def check_domains(domains):
|
|
632
626
|
sys.stderr.write(
|
633
627
|
"Error: Domain contains illegal character '/' in it.\n")
|
634
628
|
print " Did you use a URL instead of just the domain?\n"
|
635
|
-
print "Examples: -d example.com -d '*.example.com' -d
|
629
|
+
print "Examples: -d example.com -d '*.example.com' -d another.site"
|
636
630
|
print
|
637
631
|
raise SystemExit(1)
|
638
632
|
|
@@ -640,7 +634,7 @@ def check_domains(domains):
|
|
640
634
|
if all(map(lambda c: c.isdigit() or c == '.', dom)):
|
641
635
|
sys.stderr.write("Error: Domain must be a hostname not an IP\n")
|
642
636
|
print
|
643
|
-
print "Examples: -d example.com -d '*.example.com' -d
|
637
|
+
print "Examples: -d example.com -d '*.example.com' -d another.site"
|
644
638
|
print
|
645
639
|
raise SystemExit(1)
|
646
640
|
|
@@ -650,7 +644,16 @@ def check_domains(domains):
|
|
650
644
|
sys.stderr.write(
|
651
645
|
"Error: Domain requires a TLD of 2 characters or more\n")
|
652
646
|
print
|
653
|
-
print "Example: -d example.tld -d '*.example.tld' -d
|
647
|
+
print "Example: -d example.tld -d '*.example.tld' -d another.tld"
|
648
|
+
print
|
649
|
+
raise SystemExit(1)
|
650
|
+
|
651
|
+
# *.com will break uploading to S3
|
652
|
+
if dom == "*.com":
|
653
|
+
sys.stderr.write(
|
654
|
+
"Error: Matching *.com will break videos and logs. Use a hostname.\n")
|
655
|
+
print
|
656
|
+
print "Example: -d example.com -d *.example.com"
|
654
657
|
print
|
655
658
|
raise SystemExit(1)
|
656
659
|
|
@@ -709,16 +712,20 @@ Performance tip:
|
|
709
712
|
og.add_option("--readyfile",
|
710
713
|
help="Path of the file to drop when the tunnel is ready "
|
711
714
|
"for tests to run. By default, no file is dropped.")
|
715
|
+
og.add_option("--use-ssh-config", action="store_true", default=False,
|
716
|
+
help="Use the local SSH config. WARNING: Turning this on "
|
717
|
+
"may break the script!")
|
718
|
+
og.add_option("--rest-url", default="https://saucelabs.com/rest",
|
719
|
+
help=optparse.SUPPRESS_HELP)
|
720
|
+
og.add_option("--allow-unclean-exit", action="store_true", default=False,
|
721
|
+
help=optparse.SUPPRESS_HELP)
|
712
722
|
op.add_option_group(og)
|
713
723
|
|
714
724
|
og = optparse.OptionGroup(op, "Script debugging options")
|
715
|
-
og.add_option("--
|
716
|
-
help="
|
717
|
-
og.add_option("--debug-ssh", action="store_true", default=False)
|
725
|
+
og.add_option("--debug-ssh", action="store_true", default=False,
|
726
|
+
help="Log SSH output.")
|
718
727
|
og.add_option("--latency-log", type=int, default=LATENCY_LOG,
|
719
|
-
help="Threshold
|
720
|
-
"logged. [%default]")
|
721
|
-
og.add_option("--allow-unclean-exit", action="store_true", default=False)
|
728
|
+
help="Threshold for logging latency (ms) [%default]")
|
722
729
|
op.add_option_group(og)
|
723
730
|
|
724
731
|
(options, args) = op.parse_args()
|
@@ -872,8 +879,10 @@ def run(options, dependency_versions=None):
|
|
872
879
|
logger.info("** Please contact help@saucelabs.com")
|
873
880
|
peace_out(tunnel, returncode=1) # exits
|
874
881
|
|
875
|
-
ssh = ReverseSSH(tunnel, options.host,
|
876
|
-
options.
|
882
|
+
ssh = ReverseSSH(tunnel=tunnel, host=options.host,
|
883
|
+
ports=options.ports, tunnel_ports=options.tunnel_ports,
|
884
|
+
use_ssh_config=options.use_ssh_config,
|
885
|
+
debug=options.debug_ssh)
|
877
886
|
try:
|
878
887
|
ssh.run(options.readyfile)
|
879
888
|
except (ReverseSSHError, TunnelMachineError), e:
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sauce
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 41
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 12
|
9
|
-
-
|
10
|
-
version: 0.12.
|
9
|
+
- 3
|
10
|
+
version: 0.12.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sean Grove
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-12-
|
19
|
+
date: 2010-12-16 00:00:00 -08:00
|
20
20
|
default_executable: sauce
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|