sauce 0.20.0 → 1.0.0

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.
@@ -1,13 +1,12 @@
1
- Sauce OnDemand is a Selenium testing cloud service, developed by Sauce
2
- Labs Inc (saucelabs.com). This is the Ruby client adapter for Sauce
3
- OnDemand.
1
+ Sauce OnDemand is a Selenium testing cloud service, developed by Sauce Labs Inc
2
+ (saucelabs.com). This is the Ruby client adapter for Sauce OnDemand.
4
3
 
5
4
  Features
6
5
  --------
7
6
 
8
7
  * Drop-in replacement for Selenium::Client::Driver that takes care of connecting to Sauce OnDemand
9
8
  * RSpec, Test::Unit, and Rails integration for tests, including automatic setup of Sauce Connect
10
- * ActiveRecord-like interface for tunnels and jobs: Find/create/destroy
9
+ * ActiveRecord-like interface for job metadata: Find/create/destroy
11
10
 
12
11
  Install
13
12
  -------
@@ -189,12 +188,6 @@ If you want tests to go a bit faster, globally install the gems with native exte
189
188
  * gem install ffi sqlite3 json
190
189
  * rvm use default
191
190
 
192
- Plans
193
- -----
194
-
195
- * Webrat integration
196
- * Extend to automatic retrieval of jobs logs, videos, reverse tunnels
197
-
198
191
  Copyright
199
192
  ---------
200
193
 
@@ -1,6 +1,4 @@
1
- require 'rubygems'
2
1
  require 'sauce/utilities'
3
- require 'sauce/tunnel'
4
2
  require 'sauce/job'
5
3
  require 'sauce/client'
6
4
  require 'sauce/config'
@@ -9,7 +9,7 @@ module Sauce
9
9
 
10
10
  attr_accessor :client
11
11
  attr_accessor :protocol, :host, :port, :api_path, :api_version, :ip, :api_url
12
- attr_accessor :tunnels, :jobs
12
+ attr_accessor :jobs
13
13
 
14
14
  def initialize(options={})
15
15
  config = Sauce::Config.new
@@ -24,13 +24,6 @@ module Sauce
24
24
  @api_url = "#{@protocol}://#{config.username}:#{config.access_key}@#{@host}:#{@port}/#{@api_path}/v#{@api_version}/#{config.username}/"
25
25
  @client = RestClient::Resource.new @api_url
26
26
 
27
- @tunnels = Sauce::Tunnel
28
- @tunnels.client = @client
29
- @tunnels.account = {
30
- :username => config.username,
31
- :access_key => config.access_key,
32
- :ip => @ip}
33
-
34
27
  @jobs = Sauce::Job
35
28
  @jobs.client = @client
36
29
  @jobs.account = {
@@ -1,8 +1,3 @@
1
- require 'net/telnet'
2
- require 'net/ssh'
3
- require 'net/ssh/gateway'
4
- require 'sauce/gateway_ext'
5
-
6
1
  module Sauce
7
2
  # Interact with a Sauce Labs selenium jobs as if it were a ruby object
8
3
  class Job
@@ -2,13 +2,13 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{sauce}
5
- s.version = "0.20.0"
5
+ s.version = "1.0.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Eric Allen", "Sean Grove", "Steven Hazel"]
9
- s.date = %q{2011-03-26}
9
+ s.date = %q{2011-04-11}
10
10
  s.default_executable = %q{sauce}
11
- s.description = %q{A Ruby interface to Sauce Labs' services. Start/stop tunnels, retrieve Selenium logs, access video replays, etc.}
11
+ s.description = %q{A Ruby interface to Sauce OnDemand.}
12
12
  s.email = %q{help@saucelabs.com}
13
13
  s.executables = ["sauce"]
14
14
  s.files = [
@@ -30,13 +30,11 @@ Gem::Specification.new do |s|
30
30
  "lib/sauce/client.rb",
31
31
  "lib/sauce/config.rb",
32
32
  "lib/sauce/connect.rb",
33
- "lib/sauce/gateway_ext.rb",
34
33
  "lib/sauce/heroku.rb",
35
34
  "lib/sauce/integrations.rb",
36
35
  "lib/sauce/job.rb",
37
36
  "lib/sauce/raketasks.rb",
38
37
  "lib/sauce/selenium.rb",
39
- "lib/sauce/tunnel.rb",
40
38
  "lib/sauce/utilities.rb",
41
39
  "sauce.gemspec",
42
40
  "support/sauce_connect",
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: 79
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 20
9
9
  - 0
10
- version: 0.20.0
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Eric Allen
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2011-03-26 00:00:00 -07:00
20
+ date: 2011-04-11 00:00:00 -07:00
21
21
  default_executable: sauce
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
@@ -142,7 +142,7 @@ dependencies:
142
142
  version: 1.5.0
143
143
  type: :runtime
144
144
  version_requirements: *id008
145
- description: A Ruby interface to Sauce Labs' services. Start/stop tunnels, retrieve Selenium logs, access video replays, etc.
145
+ description: A Ruby interface to Sauce OnDemand.
146
146
  email: help@saucelabs.com
147
147
  executables:
148
148
  - sauce
@@ -169,13 +169,11 @@ files:
169
169
  - lib/sauce/client.rb
170
170
  - lib/sauce/config.rb
171
171
  - lib/sauce/connect.rb
172
- - lib/sauce/gateway_ext.rb
173
172
  - lib/sauce/heroku.rb
174
173
  - lib/sauce/integrations.rb
175
174
  - lib/sauce/job.rb
176
175
  - lib/sauce/raketasks.rb
177
176
  - lib/sauce/selenium.rb
178
- - lib/sauce/tunnel.rb
179
177
  - lib/sauce/utilities.rb
180
178
  - sauce.gemspec
181
179
  - support/sauce_connect
@@ -1,40 +0,0 @@
1
- # NOTE: This has been superseded by sauce/connect. Consider for deprecation
2
-
3
- # http://groups.google.com/group/capistrano/browse_thread/thread/455c0c8a6faa9cc8?pli=1
4
- class Net::SSH::Gateway
5
- # Opens a SSH tunnel from a port on a remote host to a given host and port
6
- # on the local side
7
- # (equivalent to openssh -R parameter)
8
- def open_remote(port, host, remote_port, remote_host = "127.0.0.1")
9
- ensure_open!
10
-
11
- begin
12
- @session_mutex.synchronize do
13
- result = @session.forward.remote(port, host, remote_port, remote_host)
14
- end
15
-
16
- if block_given?
17
- begin
18
- yield [remote_port, remote_host]
19
- ensure
20
- close_remote(remote_port, remote_host)
21
- end
22
- else
23
- return [remote_port, remote_host]
24
- end
25
- rescue Errno::EADDRINUSE
26
- retry
27
- end
28
- end
29
-
30
- # Cancels port-forwarding over an open port that was previously opened via
31
- # #open_remote.
32
- def close_remote(port, host = "127.0.0.1")
33
- puts "Close the remote port #{host}:#{port}!"
34
- ensure_open!
35
-
36
- @session_mutex.synchronize do
37
- @session.forward.cancel_remote(port, host)
38
- end
39
- end
40
- end
@@ -1,239 +0,0 @@
1
- # NOTE: This has been superseded by sauce/connect. Consider for deprecation
2
-
3
- require 'net/telnet'
4
- require 'net/ssh'
5
- require 'net/ssh/gateway'
6
- require 'sauce/gateway_ext'
7
-
8
- module Sauce
9
- # Interact with a Sauce Labs tunnel as if it were a ruby object
10
- class Tunnel
11
- class NoIDError < StandardError; end #nodoc
12
-
13
- #{"Status": "running", "CreationTime": 1266545716, "ModificationTime": 1266545793, "Host": "ec2-184-73-16-13.compute-1.amazonaws.com", "LaunchTime": 1266545726, "Owner": "sgrove", "_id": "1090b4b0b50477cf40fc44c146b408a4", "Type": "tunnel", "id": "1090b4b0b50477cf40fc44c146b408a4", "DomainNames": ["sgrove.tst"]}
14
-
15
- attr_accessor :owner, :access_key, :status
16
- attr_accessor :id, :host, :domain_names, :timeout
17
- attr_accessor :launch_time, :created_at, :updated_at
18
-
19
- attr_accessor :application_address, :gateway, :port, :thread
20
-
21
- # Get the class @@client.
22
- # TODO: Consider metaprogramming this away
23
- def self.client
24
- @@client
25
- end
26
-
27
- # Set the class @@client.
28
- # TODO: Consider metaprogramming this away
29
- def self.client=(client)
30
- @@client = client
31
- end
32
-
33
- # Get the class @@client.
34
- # TODO: Consider metaprogramming this away
35
- def self.account
36
- @@account
37
- end
38
-
39
- # Set the class @@client.
40
- # TODO: Consider metaprogramming this away
41
- def self.account=(account)
42
- @@account = account
43
- end
44
-
45
- def self.first
46
- self.all.first
47
- end
48
-
49
- def self.last
50
- self.all.last
51
- end
52
-
53
- def self.all
54
- responses = JSON.parse @@client[:tunnels].get.body
55
- return responses.collect{|response| Sauce::Tunnel.new(response)}
56
- end
57
-
58
- def self.destroy_all
59
- self.all.each { |tunnel| tunnel.destroy }
60
- end
61
-
62
- # Creates a new tunnel machine
63
- def self.create(options)
64
- response = JSON.parse @@client[:tunnels].post(options.to_json, :content_type => 'application/json').body
65
- #puts response.inspect
66
- Tunnel.new response
67
- end
68
-
69
- # Creates an instance representing a machine, but does not actually create the machine. See #create for that.
70
- def initialize(options)
71
- build!(options)
72
- end
73
-
74
- # Hits the destroy url for this tunnel, and then refreshes. Keep in mind it takes some time to completely teardown a tunnel.
75
- def destroy
76
- close_gateway
77
- response = @@client["tunnels/#{@id}"].delete.body
78
- refresh!
79
- end
80
-
81
- # Retrieves the latest information on this tunnel from the Sauce Labs' server
82
- def refresh!
83
- response = JSON.parse @@client["tunnels/#{@id}"].get.body
84
- #puts "\Tunnel refresh with: #{response.inspect}"
85
- build! response
86
- self
87
- end
88
-
89
- # Shortcut method to find out if a tunnel is marked as dead
90
- def preparing?
91
- refresh!
92
- status == "new" or status == "booting"
93
- end
94
-
95
- # Shortcut method to find out if a tunnel is marked as dead
96
- def halting?
97
- refresh!
98
- status == "halting"
99
- end
100
-
101
- # Shortcut method to find out if a tunnel is marked as dead
102
- def terminated?
103
- refresh!
104
- status == "terminated"
105
- end
106
-
107
- # A tunnel is healthy if 1.) its status is "running" and 2.) It says hello
108
- def healthy?
109
- # TODO: Implement 3.) We can reach through and touch a service on the reverse end of the tunnel
110
- refresh!
111
- =begin
112
- puts "\tRunning? #{self.status == 'running'}"
113
- puts "\tSays hello? #{self.says_hello?}"
114
- puts "\tThread running? #{self.still_running?}"
115
- =end
116
- return true if not self.terminated? and self.status == "running" and self.says_hello? and self.still_running?
117
- return false
118
- end
119
-
120
- # Sauce Labs' server will say hello on port 1025 as a sanity check. If no hello, something is wrong.
121
- # TODO: Make it say hello on port 1025. Currently a hack.
122
- def says_hello?(options={})
123
- return false unless self.status == "running" and not @host.nil?
124
-
125
- # TODO: Read from options if necessary
126
- connection = {}
127
- connection[:host] = @host
128
- connection[:port] = 22
129
- connection[:prompt] = /[$%#>] \z/n
130
- connection[:telnet_mode] = true
131
- connection[:timeout] = 10
132
-
133
- host = Net::Telnet::new("Host" => connection[:host],
134
- "Port" => connection[:port],
135
- "Prompt" => connection[:prompt],
136
- "Telnetmode" => connection[:telnet_mode],
137
- "Timeout" => connection[:timeout])
138
- line = host.lines.first.chomp
139
-
140
- # Temporary workaround port 1025 problem
141
- prefix = "SSH-2.0-Twisted"
142
- line[0,prefix.length] == prefix
143
- end
144
-
145
- # Debug method
146
- def mini_repair
147
- refresh!
148
- if not self.terminated? and self.status == "running" and self.says_hello?
149
- if not self.still_running?
150
- open_gateway
151
- return true if self.still_running?
152
- end
153
- end
154
- return false
155
- end
156
-
157
- # Opens a reverse ssh tunnel to the tunnel machine
158
- def open_gateway
159
- # TODO: Make ports configurable
160
-
161
- @gateway = Net::SSH::Gateway.new(host, owner, {:password => @@account[:access_key]})
162
-
163
- # Notes for anyone looking at this method
164
- # gateway.open_remote(3000, # Port where your local application is running. Usually 3000 for rails dev
165
- # "localhost", # Hostname/local ip your rails app is running on. Usually "localhost" for rails dev
166
- # 80, # This is the port to run your selenium tests against, i.e. :url => "http://<some_host>:80"
167
- # # <some_host> is the DomainNames you started the tunnel machine with.
168
- # "0.0.0.0") # Do not change this unless your god has commanded you to do so. I'm serious.
169
- port = 3000
170
- local_host = "localhost"
171
- remote_port = 80
172
- #puts "This is the experimental non-blocking gateway_open. Well done."
173
- #puts "gateway.open_remote(#{port}, #{local_host}, #{remote_port}, 0.0.0.0)"
174
- #gateway.open_remote(pair[0], local_host, pair[1], "0.0.0.0") do |rp, rh|
175
-
176
- @thread = Thread.new(host, port, remote_port, owner, @@account[:access_key]) do
177
- Thread.pass
178
- @gateway.open_remote(3000,
179
- "localhost",
180
- 80,
181
- "0.0.0.0") do |rp, rh|
182
- while true do
183
- sleep 10
184
- end
185
- end
186
- end
187
-
188
- @thread.run
189
- end
190
-
191
- # Closes the reverse ssh tunnel if open
192
- def close_gateway
193
- @thread.kill if @thread
194
- end
195
-
196
- # Returns true if this tunnel has a thread that needs to be monitored
197
- def still_running?
198
- #puts "\t\t#{@thread.inspect}.nil?"
199
- not @thread.nil?
200
- end
201
-
202
- # Returns a json representation of the current state of the tunnel object
203
- def to_json(options={})
204
- json = {
205
- :id => @id,
206
- :owner => @owner,
207
- :status => @status,
208
- :host => @host,
209
- :creation_time => @creation_time,
210
- :start_time => @start_time,
211
- :end_time => @end_time,
212
- :domain_name => @domain_names
213
- }
214
-
215
- options[:except].each { |key| json.delete(key) } if options[:except]
216
- json = json.select { |key,value| options[:only].include? key } if options[:only]
217
-
218
- return json
219
- end
220
-
221
- protected
222
-
223
- # Sets all internal variables from a hash
224
- def build!(options)
225
- options = options["tunnel"] unless options["tunnel"].nil?
226
- #puts "\tBuild with #{options.inspect}"
227
- @status = options["status"]
228
- @owner = options["owner"]
229
- @id = options["id"]
230
- @host = options["host"]
231
- @creation_time = options["creation_time"]
232
- @start_time = options["start_time"]
233
- @end_time = options["end_time"]
234
- @domain_names = options["domain_names"]
235
-
236
- raise NoIDError if @id.nil?
237
- end
238
- end
239
- end