sauce_connect 3.6.1
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.
- 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:
|