solano 1.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +15 -0
  2. data/bin/solano +29 -0
  3. data/bin/tddium +29 -0
  4. data/lib/solano.rb +19 -0
  5. data/lib/solano/agent.rb +3 -0
  6. data/lib/solano/agent/solano.rb +128 -0
  7. data/lib/solano/cli.rb +25 -0
  8. data/lib/solano/cli/api.rb +368 -0
  9. data/lib/solano/cli/commands/account.rb +50 -0
  10. data/lib/solano/cli/commands/activate.rb +16 -0
  11. data/lib/solano/cli/commands/api.rb +15 -0
  12. data/lib/solano/cli/commands/config.rb +78 -0
  13. data/lib/solano/cli/commands/console.rb +85 -0
  14. data/lib/solano/cli/commands/describe.rb +104 -0
  15. data/lib/solano/cli/commands/find_failing.rb +64 -0
  16. data/lib/solano/cli/commands/heroku.rb +17 -0
  17. data/lib/solano/cli/commands/hg.rb +48 -0
  18. data/lib/solano/cli/commands/keys.rb +81 -0
  19. data/lib/solano/cli/commands/login.rb +37 -0
  20. data/lib/solano/cli/commands/logout.rb +14 -0
  21. data/lib/solano/cli/commands/password.rb +26 -0
  22. data/lib/solano/cli/commands/rerun.rb +59 -0
  23. data/lib/solano/cli/commands/server.rb +21 -0
  24. data/lib/solano/cli/commands/spec.rb +401 -0
  25. data/lib/solano/cli/commands/status.rb +117 -0
  26. data/lib/solano/cli/commands/stop.rb +19 -0
  27. data/lib/solano/cli/commands/suite.rb +110 -0
  28. data/lib/solano/cli/commands/support.rb +24 -0
  29. data/lib/solano/cli/commands/web.rb +29 -0
  30. data/lib/solano/cli/config.rb +246 -0
  31. data/lib/solano/cli/params_helper.rb +66 -0
  32. data/lib/solano/cli/prompt.rb +128 -0
  33. data/lib/solano/cli/show.rb +136 -0
  34. data/lib/solano/cli/solano.rb +208 -0
  35. data/lib/solano/cli/suite.rb +104 -0
  36. data/lib/solano/cli/text_helper.rb +16 -0
  37. data/lib/solano/cli/timeformat.rb +21 -0
  38. data/lib/solano/cli/util.rb +132 -0
  39. data/lib/solano/constant.rb +581 -0
  40. data/lib/solano/scm.rb +18 -0
  41. data/lib/solano/scm/configure.rb +37 -0
  42. data/lib/solano/scm/git.rb +349 -0
  43. data/lib/solano/scm/git_log_parser.rb +67 -0
  44. data/lib/solano/scm/hg.rb +263 -0
  45. data/lib/solano/scm/hg_log_parser.rb +66 -0
  46. data/lib/solano/scm/scm.rb +119 -0
  47. data/lib/solano/scm/scm_stub.rb +9 -0
  48. data/lib/solano/scm/url.rb +75 -0
  49. data/lib/solano/script.rb +12 -0
  50. data/lib/solano/script/git-remote-hg +1258 -0
  51. data/lib/solano/ssh.rb +66 -0
  52. data/lib/solano/util.rb +63 -0
  53. data/lib/solano/version.rb +5 -0
  54. metadata +413 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MmY5ZWMxY2NlNjVhZGIyYzkxZjU1NzZmNGYyMjQ3YThhYzY3ZWYyYg==
5
+ data.tar.gz: !binary |-
6
+ YjMzNTIxZTAzODczOTIzZTUzYWZjYjIxZGFjODg3ODQxMzc3MjlmZQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YWUzNzA1M2Q3NTg0M2U3ZmE0ZDFiMGM2ZWZlMDkwYjIyZTNkY2Q1Y2EyNDI0
10
+ N2JkN2E2MGE0YmQxNGYxMmVmMTA2NzM4ZjUzMmYxOGY0YzNhZTRmNmQ3ODYz
11
+ YmVlOTIyNjU0MjVlMTNjZDEzZmEyMzgzYjhkYjA5MGRhNzE0YWI=
12
+ data.tar.gz: !binary |-
13
+ NGI0ZjI0NDZiZTBkZmYyYWQxM2I4NWMxNDI1MDJlZjY0MDE5NTQ5ODlhYWVm
14
+ OThjOTEwMzkxNDIyMGI5NDgzYzhiOWQ2ZDIxNTk1NzczNTYyYzUxY2Q4ZTRj
15
+ Mzk3YmZlOTVkZTNkOWRiZmRiOTczNDdmMWZjZmIxZGRiNDA0Njc=
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
4
+ #
5
+
6
+ require 'yaml'
7
+
8
+ if RUBY_VERSION < "2.1.0" && defined?(YAML::ENGINE) then
9
+ YAML::ENGINE.yamler = 'syck'
10
+ end
11
+
12
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
13
+
14
+ if ENV['COVERAGE']
15
+ begin
16
+ require 'rubygems'
17
+ require 'simplecov'
18
+ SimpleCov.root(ENV['COVERAGE_ROOT'])
19
+ SimpleCov.start do
20
+ add_group "Commands", "lib/cli/solano/commands"
21
+ end
22
+ rescue => e
23
+ STDERR.puts "Can't load simplecov: #{e.inspect} #{e.backtrace}"
24
+ end
25
+ end
26
+
27
+ require "solano"
28
+ require "solano/cli"
29
+ Solano::SolanoCli.start
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
4
+ #
5
+
6
+ require 'yaml'
7
+
8
+ if RUBY_VERSION < "2.1.0" && defined?(YAML::ENGINE) then
9
+ YAML::ENGINE.yamler = 'syck'
10
+ end
11
+
12
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
13
+
14
+ if ENV['COVERAGE']
15
+ begin
16
+ require 'rubygems'
17
+ require 'simplecov'
18
+ SimpleCov.root(ENV['COVERAGE_ROOT'])
19
+ SimpleCov.start do
20
+ add_group "Commands", "lib/cli/solano/commands"
21
+ end
22
+ rescue => e
23
+ STDERR.puts "Can't load simplecov: #{e.inspect} #{e.backtrace}"
24
+ end
25
+ end
26
+
27
+ require "solano"
28
+ require "solano/cli"
29
+ Solano::SolanoCli.start
@@ -0,0 +1,19 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ require "solano/constant"
4
+ require "solano/version"
5
+
6
+ require "solano/util"
7
+
8
+ require "solano/scm"
9
+ require "solano/ssh"
10
+
11
+ module Solano
12
+ class SolanoError < Exception
13
+ attr_reader :message
14
+
15
+ def initialize(message)
16
+ @message = message
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ require 'solano/agent/solano'
@@ -0,0 +1,128 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014, 2015 Solano Labs All Rights Reserved
2
+
3
+ require 'json'
4
+ require 'fileutils'
5
+ require 'securerandom'
6
+ require 'tddium_client'
7
+
8
+ module Solano
9
+ class BuildAgent
10
+ MAXIMUM_ATTACHMENT_SIZE = 16*1024*1024
11
+
12
+ def initialize
13
+ end
14
+
15
+ # @return Boolean indicating whether or not we are running inside Solano
16
+ def solano?
17
+ return ENV.member?('SOLANO') || ENV.member?('TDDIUM')
18
+ end
19
+
20
+ # @return The current worker thread ID
21
+ # @note Id is not unique across workers; there is no accessible GUID
22
+ def thread_id
23
+ return fetch_id('TID')
24
+ end
25
+
26
+ # @return Current session ID
27
+ def session_id
28
+ return fetch_id('SESSION_ID')
29
+ end
30
+
31
+ # @return Per-execution unique ID of currently running test
32
+ def test_exec_id
33
+ return fetch_id('TEST_EXEC_ID')
34
+ end
35
+
36
+ # @return Solano environment (batch, interactive, etc.)
37
+ def environment
38
+ env = ENV['SOLANO_MODE'] || 'none'
39
+ return env
40
+ end
41
+
42
+ # Status of build
43
+ # @param which :current or :last
44
+ # @return 'passed', 'failed', 'error', or 'unknown'
45
+ def build_status(which=:current)
46
+ status = 'unknown'
47
+ case which
48
+ when :current
49
+ status = ENV['SOLANO_BUILD_STATUS']
50
+ when :last
51
+ status = ENV['SOLANO_LAST_BUILD_STATUS']
52
+ end
53
+ status ||= 'unknown'
54
+ return status
55
+ end
56
+
57
+ # BOTCH: must be SCM agnostic
58
+ def current_branch
59
+ cmd = "cd #{ENV['SOLANO_REPO_ROOT']} && git symbolic-ref HEAD"
60
+ `#{cmd}`.gsub("\n", "").split("/")[2..-1].join("/")
61
+ end
62
+
63
+ # Attach a blob to the session -- excessive storage use is billable
64
+ # @param data blob that is convertible into a string
65
+ # @param metadata hash of metadata options
66
+ # @note See attach_file for description of options
67
+ def attach(data, metadata)
68
+ if data.size > MAXIMUM_ATTACHMENT_SIZE then
69
+ raise SolanoError.new("Data are too large to attach to session")
70
+ end
71
+
72
+ if !metadata.member?(:name) then
73
+ guid = SecureRandom.hex(4)
74
+ metadata[:name] = "user.#{guid}.dat"
75
+ end
76
+
77
+ guid = SecureRandom.hex(8)
78
+ temp_path = File.join(ENV['HOME'], 'tmp', "attach-#{guid}.dat")
79
+ File.open(temp_path, File::CREAT|File::TRUNC|File::RDWR, 0600) do |file|
80
+ file.write(data)
81
+ attach_file(temp_path, metadata)
82
+ end
83
+ end
84
+
85
+ # Attach a blob to the session -- excessive storage use is billable
86
+ # @param data blob that is convertible into a string
87
+ # @param [Hash] metadata hash of metadata options
88
+ # @option metadata [String] :name Override name of attachment
89
+ # @option metadata [String] :exec_id Attach to named test execution
90
+ def attach_file(path, metadata={})
91
+ if !File.exists?(path) then
92
+ raise Errno::ENOENT.new(path)
93
+ end
94
+ if File.size(path) > MAXIMUM_ATTACHMENT_SIZE then
95
+ raise SolanoError.new("Data are too large to attach to session")
96
+ end
97
+ name = metadata[:name] || File.basename(path)
98
+ attach_path = attachment_path(name, metadata[:exec_id])
99
+ FileUtils.cp(path, attach_path)
100
+ end
101
+
102
+ # FUTURE: convert to call to internal agent API server
103
+ # Unregistered and authenticated files will be ignored
104
+ def attachment_path(name, exec_id=nil)
105
+ path = File.join(ENV['HOME'], 'results', session_id.to_s)
106
+ if exec_id.nil? then
107
+ path = File.join(path, 'session', name)
108
+ else
109
+ path = File.join(path, exec_id.to_s, name)
110
+ end
111
+ return path
112
+ end
113
+
114
+ protected
115
+
116
+ def fetch_id(name)
117
+ return nil unless solano?
118
+ %w(TDDIUM SOLANO).each do |prefix|
119
+ qualified_name = "#{prefix}_#{name}"
120
+ if ENV.member?(qualified_name) then
121
+ id = ENV[qualified_name]
122
+ return id.to_i
123
+ end
124
+ end
125
+ return nil
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ require 'rubygems'
4
+ require 'thor'
5
+ require 'highline/import'
6
+ require 'json'
7
+ require 'launchy'
8
+ require 'tddium_client'
9
+ require 'shellwords'
10
+ require 'base64'
11
+ require 'msgpack_pure'
12
+ require 'erb'
13
+
14
+ require 'solano/script'
15
+ require 'solano/cli/params_helper'
16
+ require 'solano/cli/solano'
17
+
18
+ require 'solano/cli/api'
19
+ require 'solano/cli/config'
20
+ require 'solano/cli/suite'
21
+ require 'solano/cli/prompt'
22
+ require 'solano/cli/show'
23
+ require 'solano/cli/util'
24
+ require 'solano/cli/text_helper'
25
+ require 'solano/cli/timeformat'
@@ -0,0 +1,368 @@
1
+ # Copyright (c) 2011-2016 Solano Labs All Rights Reserved
2
+
3
+ module Solano
4
+ class SolanoAPI
5
+ include SolanoConstant
6
+
7
+ attr_reader :scm # rspec
8
+
9
+ def initialize(scm, tddium_client, api_config, options={})
10
+ @scm = scm
11
+ @api_config = api_config
12
+ @tddium_client = tddium_client
13
+ @tddium_clientv3 = options[:v3]
14
+ end
15
+
16
+ def call_api(method, api_path, params = {}, api_key = nil, show_error = true)
17
+ api_key ||= @api_config.get_api_key unless api_key == false
18
+
19
+ if params[:v3]
20
+ api = @tddium_clientv3
21
+ params.delete(:v3)
22
+ end
23
+ api ||= @tddium_client
24
+
25
+ begin
26
+ result = api.call_api(method, api_path, params, api_key)
27
+ rescue TddiumClient::Error::UpgradeRequired => e
28
+ abort e.message
29
+ rescue TddiumClient::Error::APICert => e
30
+ abort e.message
31
+ rescue TddiumClient::Error::Base => e
32
+ say e.message.dup if show_error
33
+ raise e
34
+ end
35
+ result
36
+ end
37
+
38
+ def get_single_account_id
39
+ user_details = user_logged_in?(true, false)
40
+ return nil unless user_details
41
+ accounts = user_details["participating_accounts"]
42
+ unless accounts.length == 1
43
+ msg = "You are a member of more than one organization.\n"
44
+ msg << "Please specify the organization you want to operate on with "
45
+ msg << "'--org NAME'.\n"
46
+ accounts.each do |acct|
47
+ msg << " #{acct["account"]}\n"
48
+ end
49
+ raise msg
50
+ end
51
+ accounts.first["account_id"]
52
+ end
53
+
54
+ def get_account_id(acct_name)
55
+ user_details = user_logged_in?(true, false)
56
+ return nil unless user_details
57
+ accts = user_details["participating_accounts"]
58
+ acct = accts.select{|acct| acct["account"] == acct_name}.first
59
+ if acct.nil?
60
+ raise "You aren't a member of organization '%s'." % acct_name
61
+ end
62
+ acct["account_id"]
63
+ end
64
+
65
+ def env_path(scope, key=nil)
66
+ account_id = nil
67
+ if @api_config.cli_options[:account] then
68
+ account_id = get_account_id(@api_config.cli_options[:account])
69
+ end
70
+ if account_id.nil? then
71
+ account_id = get_single_account_id
72
+ end
73
+ path = ['']
74
+
75
+ case scope
76
+ when "suite"
77
+ path << 'suites'
78
+ path << current_suite_id
79
+ when "repo"
80
+ path << 'repos'
81
+ path << current_repo_id
82
+ when "org"
83
+ path << 'accounts'
84
+ path << account_id
85
+ else
86
+ raise "Unrecognized scope. Use 'suite', 'repo', 'org'."
87
+ end
88
+
89
+ path << 'env'
90
+ path << key if key
91
+ path.join('/')
92
+ end
93
+
94
+ def get_config_key(scope, key=nil)
95
+ path = env_path(scope, key)
96
+ call_api(:get, path)
97
+ end
98
+
99
+ def set_config_key(scope, key, value)
100
+ path = env_path(scope)
101
+ call_api(:post, path, :env=>{key=>value})
102
+ end
103
+
104
+ def delete_config_key(scope, key)
105
+ path = env_path(scope, key)
106
+ call_api(:delete, path)
107
+ end
108
+
109
+ def get_user(api_key=nil)
110
+ result = call_api(:get, Api::Path::USERS, {}, api_key, false)
111
+ result && result['user']
112
+ end
113
+
114
+ def set_user(params)
115
+ call_api(:post, Api::Path::USERS, {:user => params}, false, false)
116
+ end
117
+
118
+ def update_user(user_id, params, api_key=nil)
119
+ call_api(:put, "#{Api::Path::USERS}/#{user_id}/", params, api_key, false)
120
+ end
121
+
122
+ def get_user_credentials(options = {})
123
+ params = {}
124
+
125
+ if options[:cli_token]
126
+ params[:cli_token] = options[:cli_token]
127
+ elsif options[:invited]
128
+ # prompt for email/invitation and password
129
+ token = options[:invitation_token] || ask(Text::Prompt::INVITATION_TOKEN)
130
+ params[:invitation_token] = token.strip
131
+ params[:password] = options[:password] || HighLine.ask(Text::Prompt::NEW_PASSWORD) { |q| q.echo = "*" }
132
+ else
133
+ say Text::Warning::USE_PASSWORD_TOKEN
134
+ params[:email] = options[:email] || HighLine.ask(Text::Prompt::EMAIL)
135
+ params[:password] = options[:password] || HighLine.ask(Text::Prompt::PASSWORD) { |q| q.echo = "*" }
136
+ end
137
+ params
138
+ end
139
+
140
+ def login_user(options = {})
141
+ # POST (email, password) to /users/sign_in to retrieve an API key
142
+ begin
143
+ user = options[:params]
144
+ login_result = call_api(:post, Api::Path::SIGN_IN, {:user => user}, false, options[:show_error])
145
+ @api_config.set_api_key(login_result["api_key"], user[:email])
146
+ rescue TddiumClient::Error::Base => e
147
+ end
148
+ login_result
149
+ end
150
+
151
+ def user_logged_in?(active = true, message = false)
152
+ global_api_key = @api_config.get_api_key(:global => true)
153
+ repo_api_key = @api_config.get_api_key(:repo => true)
154
+
155
+ if (global_api_key && repo_api_key && global_api_key != repo_api_key)
156
+ say Text::Error::INVALID_CREDENTIALS if message
157
+ return
158
+ end
159
+
160
+ result = repo_api_key || global_api_key
161
+
162
+ if message && result.nil? then
163
+ say Text::Error::NOT_INITIALIZED
164
+ end
165
+
166
+ if result && active
167
+ u = get_user
168
+ if message && u.nil?
169
+ say Text::Error::INVALID_CREDENTIALS
170
+ end
171
+ u
172
+ else
173
+ result
174
+ end
175
+ end
176
+
177
+ def get_memberships(params={})
178
+ result = call_api(:get, Api::Path::MEMBERSHIPS)
179
+ result['account_roles'] || []
180
+ end
181
+
182
+ def set_memberships(params={})
183
+ result = call_api(:post, Api::Path::MEMBERSHIPS, params)
184
+ result['memberships'] || []
185
+ end
186
+
187
+ def delete_memberships(email, params={})
188
+ call_api(:delete, "#{Api::Path::MEMBERSHIPS}/#{email}", params)
189
+ end
190
+
191
+ def get_usage(params={})
192
+ result = call_api(:get, Api::Path::ACCOUNT_USAGE_BY_ACCOUNT)
193
+ result['usage'] || []
194
+ end
195
+
196
+ def get_keys(params={})
197
+ result = call_api(:get, Api::Path::KEYS)
198
+ result['keys']|| []
199
+ end
200
+
201
+ def set_keys(params)
202
+ call_api(:post, Api::Path::KEYS, params)
203
+ end
204
+
205
+ def delete_keys(name, params={})
206
+ call_api(:delete, "#{Api::Path::KEYS}/#{name}", params)
207
+ end
208
+
209
+ def default_branch
210
+ @default_branch ||= @scm.default_branch
211
+ end
212
+
213
+ def current_branch
214
+ @current_branch ||= @scm.current_branch
215
+ end
216
+
217
+ def current_repo_id(options={})
218
+ # api_config.get_branch will query the server if there is no locally cached data
219
+ @api_config.get_branch(current_branch, 'repo_id', options)
220
+ end
221
+
222
+ def current_suite_id(options={})
223
+ # api_config.get_branch will query the server if there is no locally cached data
224
+ @api_config.get_branch(current_branch, 'id', options)
225
+ end
226
+
227
+ def current_suite_options(options={})
228
+ @api_config.get_branch(current_branch, 'options', options)
229
+ end
230
+
231
+ def default_suite_id(options={})
232
+ # api_config.get_branch will query the server if there is no locally cached data
233
+ @api_config.get_branch(default_branch, 'id', options)
234
+ end
235
+
236
+ def default_suite_options(options={})
237
+ @api_config.get_branch(default_branch, 'options', options)
238
+ end
239
+
240
+ # suites/user_suites returns:
241
+ # [
242
+ # 'account',
243
+ # 'account_id',
244
+ # 'branch',
245
+ # 'ci_ssh_pubkey',
246
+ # 'git_repo_uri',
247
+ # 'id',
248
+ # 'org_name',
249
+ # 'repo_name',
250
+ # 'repo_url'
251
+ # ]
252
+ def get_suites(params={})
253
+ current_suites = call_api(:get, "#{Api::Path::SUITES}/user_suites", params)
254
+ current_suites ||= {}
255
+ current_suites['suites'] || []
256
+ end
257
+
258
+ def get_suite_by_id(id, params={})
259
+ current_suites = call_api(:get, "#{Api::Path::SUITES}/#{id}", params)
260
+ current_suites ||= {}
261
+ current_suites['suite']
262
+ end
263
+
264
+ def create_suite(params)
265
+ account_id = params.delete(:account_id)
266
+ new_suite = call_api(:post, Api::Path::SUITES, {:suite => params, :account_id => account_id})
267
+ new_suite["suite"]
268
+ end
269
+
270
+ def update_suite(id, params={})
271
+ call_api(:put, "#{Api::Path::SUITES}/#{id}", params)
272
+ end
273
+
274
+ def permanent_destroy_suite(id, params={})
275
+ call_api(:delete, "#{Api::Path::SUITES}/#{id}/permanent_destroy", params)
276
+ end
277
+
278
+ def demand_repoman_account(id, params={})
279
+ call_api(:post, "#{Api::Path::ACCOUNTS}/#{id}/demand_repoman", params)
280
+ end
281
+
282
+ def get_sessions(params={})
283
+ begin
284
+ call_api(:get, Api::Path::SESSIONS, params)['sessions']
285
+ rescue TddiumClient::Error::Base
286
+ []
287
+ end
288
+ end
289
+
290
+ def create_session(suite_id, params = {})
291
+ new_session = call_api(:post, Api::Path::SESSIONS, params.merge(:suite_id=>suite_id))
292
+ return new_session['session'], new_session['manager']
293
+ end
294
+
295
+ def get_snapshot_commit(params={})
296
+ params.merge!({:v3 => true})
297
+ call_api(:get, "#{Api::Path::REPO_SNAPSHOT}/commit_id", params)
298
+ end
299
+
300
+ def start_destrofree_session(session_id, params={})
301
+ params.merge!({:v3 => true})
302
+ call_api(:post, "#{Api::Path::SESSIONS}/#{session_id}/start", params)
303
+ end
304
+
305
+ def request_snapshot_url(params={})
306
+ params.merge!({:v3 => true})
307
+ call_api(:post, "#{Api::Path::REPO_SNAPSHOT}/request_upload_url", params)
308
+ end
309
+
310
+ def update_snapshot(params={})
311
+ params.merge!({:v3 => true})
312
+ call_api(:post, "#{Api::Path::REPO_SNAPSHOT}", params)
313
+ end
314
+
315
+ def request_patch_url(params={})
316
+ params.merge!({:v3 => true})
317
+ call_api(:post, "#{Api::Path::SESSION_PATCH}/request_url", params)
318
+ end
319
+
320
+ def upload_session_patch(params={})
321
+ params.merge!({:v3 => true})
322
+ call_api(:post, "#{Api::Path::SESSION_PATCH}", params)
323
+ end
324
+
325
+ def update_session(session_id, params={})
326
+ result = call_api(:put, "#{Api::Path::SESSIONS}/#{session_id}", params)
327
+ result['session']
328
+ end
329
+
330
+ def register_session(session_id, suite_id, test_pattern, test_exclude_pattern=nil)
331
+ args = {:suite_id => suite_id, :test_pattern => test_pattern}
332
+ if test_exclude_pattern
333
+ args[:test_exclude_pattern] = test_exclude_pattern
334
+ end
335
+
336
+ call_api(:post, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::REGISTER_TEST_EXECUTIONS}", args)
337
+ end
338
+
339
+ def start_session(session_id, params)
340
+ call_api(:post, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::START_TEST_EXECUTIONS}", params)
341
+ end
342
+
343
+ def start_console(session_id, suite_id)
344
+ path = "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::TEST_EXECUTIONS}/console"
345
+ call_api(:post, path, {suite_id: suite_id})
346
+ end
347
+
348
+ def stop_session(ls_id, params = {})
349
+ call_api(:post, "#{Api::Path::SESSIONS}/#{ls_id}/stop", params)
350
+ end
351
+
352
+ def poll_session(session_id, params={})
353
+ call_api(:get, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::TEST_EXECUTIONS}")
354
+ end
355
+
356
+ def query_session(session_id, params={})
357
+ call_api(:get, "#{Api::Path::SESSIONS}/#{session_id}")
358
+ end
359
+
360
+ def query_session_tests(session_id, params={})
361
+ call_api(:get, "#{Api::Path::SESSIONS}/#{session_id}/#{Api::Path::QUERY_TEST_EXECUTIONS}")
362
+ end
363
+
364
+ def check_session_done(session_id)
365
+ call_api(:get, "#{Api::Path::SESSIONS}/#{session_id}/check_done")
366
+ end
367
+ end
368
+ end