solano 1.31.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.
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