sauce_connect 3.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/sauce/connect.rb +242 -0
- metadata +70 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b56c2f924091bac3a7f5aca719edd393812043d6
|
4
|
+
data.tar.gz: e50ee142b53516ce21bf448a12981241b484e345
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2dbef3999ab736761308dd400f22ee5fe0f2ef67c2cd9e6dbf19f3ffff7c363119d2aa9560beba4bc302621f348e7364db2dbb21cf20cc0b8b865ad7118e066
|
7
|
+
data.tar.gz: 43e4d418185295b57f69a84806a69c768c6ff762f04d528e9550299cb8651ec8c0351007bebe9e4c981e479e8ed0a6454519285e95c600a846dddccea370e9af
|
@@ -0,0 +1,242 @@
|
|
1
|
+
require 'sauce/config'
|
2
|
+
require 'net/http'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
module Sauce
|
6
|
+
class Connect
|
7
|
+
class TunnelNotPossibleException < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
TIMEOUT = 90
|
11
|
+
|
12
|
+
attr_reader :status, :error
|
13
|
+
|
14
|
+
def initialize(options={})
|
15
|
+
@ready = false
|
16
|
+
@status = "uninitialized"
|
17
|
+
@error = nil
|
18
|
+
@quiet = options[:quiet]
|
19
|
+
@timeout = options.fetch(:timeout) { TIMEOUT }
|
20
|
+
@config = Sauce::Config.new(options)
|
21
|
+
@skip_connection_test = @config[:skip_connection_test]
|
22
|
+
@cli_options = @config[:connect_options]
|
23
|
+
@sc4_executable = @config[:sauce_connect_4_executable]
|
24
|
+
|
25
|
+
if @config.username.nil?
|
26
|
+
raise ArgumentError, "Username required to launch Sauce Connect. Please set the environment variable $SAUCE_USERNAME"
|
27
|
+
end
|
28
|
+
|
29
|
+
if @config.access_key.nil?
|
30
|
+
raise ArgumentError, "Access key required to launch Sauce Connect. Please set the environment variable $SAUCE_ACCESS_KEY"
|
31
|
+
end
|
32
|
+
|
33
|
+
if @sc4_executable.nil?
|
34
|
+
raise TunnelNotPossibleException, Sauce::Connect.plzGetSC4
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def ensure_connection_is_possible
|
39
|
+
$stderr.puts "[Checking REST API is contactable...]" unless @quiet
|
40
|
+
uri = URI("http://saucelabs.com/rest/v1/#{@config[:username]}/tunnels")
|
41
|
+
|
42
|
+
response = Net::HTTP.start(uri.host, uri.port) do |http|
|
43
|
+
request = Net::HTTP::Get.new uri.request_uri
|
44
|
+
request.basic_auth(@config[:username], @config[:access_key])
|
45
|
+
response = http.request request
|
46
|
+
end
|
47
|
+
|
48
|
+
unless response.kind_of? Net::HTTPOK
|
49
|
+
$stderr.puts Sauce::Connect.cant_access_rest_api_message
|
50
|
+
raise TunnelNotPossibleException, "Couldn't access REST API"
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
$stderr.puts "[Checking port 443 is open...]" unless @quiet
|
55
|
+
socket = TCPSocket.new 'saucelabs.com', 443
|
56
|
+
rescue SystemCallError => e
|
57
|
+
raise e unless e.class.name.start_with? 'Errno::'
|
58
|
+
$stderr.puts Sauce::Connect.port_not_open_message
|
59
|
+
raise TunnelNotPossibleException, "Couldn't use port 443"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def connect
|
64
|
+
unless @skip_connection_test
|
65
|
+
ensure_connection_is_possible
|
66
|
+
end
|
67
|
+
|
68
|
+
puts "[Sauce Connect is connecting to Sauce Labs...]"
|
69
|
+
|
70
|
+
formatted_cli_options = array_of_formatted_cli_options_from_hash(cli_options)
|
71
|
+
|
72
|
+
command_args = ['-u', @config.username, '-k', @config.access_key]
|
73
|
+
command_args << formatted_cli_options
|
74
|
+
|
75
|
+
command = "exec #{find_sauce_connect} #{command_args.join(' ')} 2>&1"
|
76
|
+
|
77
|
+
unless @quiet
|
78
|
+
string_arguments = formatted_cli_options.join(' ')
|
79
|
+
puts "[Sauce Connect arguments: '#{string_arguments}' ]"
|
80
|
+
end
|
81
|
+
|
82
|
+
@pipe = IO.popen(command)
|
83
|
+
|
84
|
+
@process_status = $?
|
85
|
+
at_exit do
|
86
|
+
Process.kill("INT", @pipe.pid)
|
87
|
+
while @ready
|
88
|
+
sleep 1
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
Thread.new {
|
93
|
+
while( (line = @pipe.gets) )
|
94
|
+
if line =~ /Tunnel remote VM is (.*) (\.\.|at)/
|
95
|
+
@status = $1
|
96
|
+
end
|
97
|
+
if line =~/You may start your tests\./i
|
98
|
+
@ready = true
|
99
|
+
end
|
100
|
+
if line =~ /- (Problem.*)$/
|
101
|
+
@error = $1
|
102
|
+
@quiet = false
|
103
|
+
end
|
104
|
+
if line =~ /== Missing requirements ==/
|
105
|
+
@error = "Missing requirements"
|
106
|
+
@quiet = false
|
107
|
+
end
|
108
|
+
if line =~/Invalid API_KEY provided/
|
109
|
+
@error = "Invalid API_KEY provided"
|
110
|
+
@quiet = false
|
111
|
+
end
|
112
|
+
$stderr.puts line unless @quiet
|
113
|
+
end
|
114
|
+
@ready = false
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def cli_options
|
119
|
+
cli_options = { readyfile: "sauce_connect.ready" }
|
120
|
+
cli_options.merge!(@cli_options) if @cli_options
|
121
|
+
cli_options
|
122
|
+
end
|
123
|
+
|
124
|
+
def wait_until_ready
|
125
|
+
start = Time.now
|
126
|
+
while !@ready and (Time.now-start) < @timeout and @error != "Missing requirements"
|
127
|
+
sleep 0.5
|
128
|
+
end
|
129
|
+
|
130
|
+
if @error == "Missing requirements"
|
131
|
+
raise "Missing requirements"
|
132
|
+
end
|
133
|
+
|
134
|
+
if !@ready
|
135
|
+
error_message = "Sauce Connect failed to connect after #{@timeout} seconds"
|
136
|
+
error_message << "\n(Using Sauce Connect at #{@sc4_executable}"
|
137
|
+
raise error_message
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def disconnect
|
142
|
+
if @ready
|
143
|
+
Process.kill("INT", @pipe.pid)
|
144
|
+
while @ready
|
145
|
+
sleep 1
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Check whether the path, or it's bin/sc descendant, exists and is executable
|
151
|
+
def find_sauce_connect
|
152
|
+
paths = [@sc4_executable, File.join("#{@sc4_executable}", "bin", "sc")]
|
153
|
+
|
154
|
+
sc_path = paths.find do |path|
|
155
|
+
path_is_connect_executable? path
|
156
|
+
end
|
157
|
+
|
158
|
+
if sc_path.nil?
|
159
|
+
raise TunnelNotPossibleException, "No executable found at #{sc_path}, or it can't be executed by #{Process.euid}"
|
160
|
+
end
|
161
|
+
|
162
|
+
return File.absolute_path sc_path
|
163
|
+
end
|
164
|
+
|
165
|
+
def path_is_connect_executable? path
|
166
|
+
absolute_path = File.absolute_path path
|
167
|
+
return (File.exist? absolute_path) && (File.executable? absolute_path) && !(Dir.exist? absolute_path)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Global Sauce Connect-ness
|
171
|
+
@connection = nil
|
172
|
+
|
173
|
+
def self.connect!(*args)
|
174
|
+
@connection = self.new(*args)
|
175
|
+
@connection.connect
|
176
|
+
@connection.wait_until_ready
|
177
|
+
at_exit do
|
178
|
+
@connection.disconnect
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.ensure_connected(*args)
|
183
|
+
if @connection
|
184
|
+
@connection.wait_until_ready
|
185
|
+
else
|
186
|
+
connect!(*args)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def array_of_formatted_cli_options_from_hash(hash)
|
193
|
+
hash.collect do |key, value|
|
194
|
+
opt_name = key.to_s.gsub("_", "-")
|
195
|
+
"--#{opt_name} #{value}"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def self.port_not_open_message
|
200
|
+
<<-ENDLINE
|
201
|
+
Unable to connect to port 443 on saucelabs.com, which may interfere with
|
202
|
+
Sauce Connect.
|
203
|
+
|
204
|
+
This might be caused by a HTTP mocking framework like WebMock or
|
205
|
+
FakeWeb. Check out
|
206
|
+
(https://github.com/saucelabs/sauce_ruby#network-mocking)
|
207
|
+
if you're using one. Sauce Connect needs access to *.saucelabs.com,
|
208
|
+
port 80 and port 443.
|
209
|
+
|
210
|
+
You can disable network tests by setting :skip_connection_test to true in
|
211
|
+
your Sauce.config block.
|
212
|
+
ENDLINE
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.cant_access_rest_api_message
|
216
|
+
<<-ENDLINE
|
217
|
+
Unable to connect to the Sauce REST API, which may interfere with
|
218
|
+
Sauce Connect.
|
219
|
+
|
220
|
+
This might be caused by a HTTP mocking framework like WebMock or
|
221
|
+
FakeWeb. Check out
|
222
|
+
(https://github.com/saucelabs/sauce_ruby#network-mocking)
|
223
|
+
if you're using one. Sauce Connect needs access to *.saucelabs.com,
|
224
|
+
port 80 and port 443.
|
225
|
+
|
226
|
+
You can disable network tests by setting :skip_connection_test to true in
|
227
|
+
your Sauce.config block.
|
228
|
+
ENDLINE
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.plzGetSC4
|
232
|
+
<<-ENDLINE
|
233
|
+
Using Sauce Connect 3 has been deprecated. Please set the :sauce_connect_4_executable
|
234
|
+
option in your Sauce.config block to the path of an installation of
|
235
|
+
Sauce Connect 4.
|
236
|
+
|
237
|
+
You can download Sauce Connect 4 for free at
|
238
|
+
http://docs.saucelabs.com/sauce_connect
|
239
|
+
ENDLINE
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sauce_connect
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.6.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- R. Tyler Croy
|
8
|
+
- Steve Hazel
|
9
|
+
- Dylan Lacey
|
10
|
+
- Rick Martínez
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2015-06-26 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: sauce_ruby
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3.5'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.5'
|
30
|
+
description: A wrapper to start and stop a Sauce Connect tunnel programatically.
|
31
|
+
email:
|
32
|
+
- tyler@monkeypox.org
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- lib/sauce/connect.rb
|
38
|
+
homepage: https://docs.saucelabs.com/reference/sauce-connect
|
39
|
+
licenses:
|
40
|
+
- Apache 2.0
|
41
|
+
metadata: {}
|
42
|
+
post_install_message: |2
|
43
|
+
To use the Sauce Connect gem, you'll need to download the appropriate
|
44
|
+
Sauce Connect binary from https://docs.saucelabs.com/reference/sauce-connect
|
45
|
+
|
46
|
+
Then, set the 'sauce_connect_4_executable' key in your Sauce.config block, to
|
47
|
+
the path of the unzipped file's /bin/sc.
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements:
|
62
|
+
- An account at http://www.saucelabs.com
|
63
|
+
- A working copy of Sauce Connect from https://docs.saucelabs.com/reference/sauce-connect
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 2.4.6
|
66
|
+
signing_key:
|
67
|
+
specification_version: 4
|
68
|
+
summary: Manage Sauce Connect from within your tests
|
69
|
+
test_files: []
|
70
|
+
has_rdoc:
|