sauce 0.12.2 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/VERSION +1 -1
  2. data/support/sauce_connect +39 -30
  3. metadata +4 -4
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.12.2
1
+ 0.12.3
@@ -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 = 20
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, debug=False):
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
- ssh_known_hosts = os.path.join(os.environ['HOME'], ".ssh", "known_hosts")
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-keygen %s -R %s;%s;"
407
- % (verbosity, self.tunnel.host, wait) +
408
- "spawn ssh-keygen %s -R %s;%s;" % (verbosity, host_ip, wait) +
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("--- fin ---")
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 cdn.example.org"
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 cdn.example.org"
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 cdn.example.tld"
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("--rest-url", default="https://saucelabs.com/rest",
716
- help="[%default]")
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 above which latency (ms) will be "
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, options.ports, options.tunnel_ports,
876
- options.debug_ssh)
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: 43
4
+ hash: 41
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 12
9
- - 2
10
- version: 0.12.2
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-15 00:00:00 -08:00
19
+ date: 2010-12-16 00:00:00 -08:00
20
20
  default_executable: sauce
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency