tesults 1.0.1 → 1.1.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.
- checksums.yaml +4 -4
- data/lib/tesults.rb +191 -8
- metadata +33 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee8de6dd8552c947659aebea45ef94cb5e6f738e
|
4
|
+
data.tar.gz: 771e0d69d0f437251875edbd5f1d7f8b56c16c16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4d84658b97a8f05b737c3efd110317e81ea1b25b7a92e35b1315f0872317ebfa688c24d3389bd7dfde86a8eedbee652a293e1783dee56c5e5df65844b84c922
|
7
|
+
data.tar.gz: 8a8a34a60c0b6381fbe389cb41c99c0fdf343d89ebfd70f16fa84ee4bdaa19df5d69c5a52cb3ee896201a371867491d60cdd16edbb00e35312d17e0c63ce93e0
|
data/lib/tesults.rb
CHANGED
@@ -1,10 +1,28 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'uri'
|
3
3
|
require 'net/https'
|
4
|
+
require 'aws-sdk'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
class Tesults
|
7
|
+
@@expire_buffer = 30 # 30 seconds
|
8
|
+
@@files_uploaded = 0
|
9
|
+
@@bytes_uploaded = 0
|
10
|
+
@@uploading = []
|
11
|
+
@@warnings = []
|
12
|
+
|
13
|
+
def self.create_s3_cilent(credentials)
|
14
|
+
s3_client = Aws::S3::Client.new(
|
15
|
+
region: 'us-east-1',
|
16
|
+
access_key_id: credentials['AccessKeyId'],
|
17
|
+
secret_access_key: credentials['SecretAccessKey'],
|
18
|
+
session_token: credentials['SessionToken']
|
19
|
+
)
|
20
|
+
Aws::S3::Resource.new(client: s3_client)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.refresh_credentials(target, key)
|
24
|
+
data = {:target => target, :key => key}
|
25
|
+
uri = URI("https://www.tesults.com/permitupload")
|
8
26
|
http = Net::HTTP.new(uri.host, uri.port)
|
9
27
|
http.use_ssl = true
|
10
28
|
req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
|
@@ -13,15 +31,180 @@ module Tesults
|
|
13
31
|
jsonData = JSON.parse(res.body)
|
14
32
|
success = false
|
15
33
|
message = ""
|
34
|
+
upload = nil
|
16
35
|
if jsonData['error'] == nil
|
17
36
|
success = true
|
18
|
-
|
37
|
+
d = jsonData['data']
|
38
|
+
message = d['message']
|
39
|
+
upload = d['upload']
|
19
40
|
else
|
20
41
|
success = false
|
21
|
-
|
42
|
+
err = jsonData['error']
|
43
|
+
message = err['message']
|
22
44
|
end
|
23
|
-
val = {:success => success, :message => message}
|
45
|
+
val = {:success => success, :message => message, :upload => upload}
|
24
46
|
rescue => e
|
25
|
-
|
47
|
+
return {:success => false, :message => e.message, :upload => nil}
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.transfer(file, bytes, key, auth)
|
52
|
+
Thread.new {
|
53
|
+
s3 = create_s3_cilent(auth)
|
54
|
+
increment = 1
|
55
|
+
bytes_increment = bytes
|
56
|
+
begin
|
57
|
+
result = s3.bucket('tesults-results').object(key).upload_file(file)
|
58
|
+
rescue
|
59
|
+
# upload failed
|
60
|
+
increment = 0
|
61
|
+
bytes_increment = 0
|
62
|
+
ensure
|
63
|
+
if result != true
|
64
|
+
increment = 0
|
65
|
+
bytes_increment = 0
|
66
|
+
end
|
67
|
+
@@files_uploaded += increment
|
68
|
+
@@bytes_uploaded += bytes_increment
|
69
|
+
@@uploading.delete_at @@uploading.index file
|
70
|
+
end
|
71
|
+
}
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.files_upload(files, keyPrefix, auth, target)
|
76
|
+
expiration_string = auth['Expiration']
|
77
|
+
expiration = expiration_string.to_i
|
78
|
+
max_active_uploads = 10 # Upload at most 10 files simultaneously to avoid hogging the client machine.
|
79
|
+
|
80
|
+
while files.length != 0 || @@uploading.length != 0 do
|
81
|
+
begin
|
82
|
+
if @@uploading.length < max_active_uploads && files.length != 0
|
83
|
+
# Check if new credentials required.
|
84
|
+
now = Time.now.to_i
|
85
|
+
if now + @@expire_buffer > expiration # Check within 30 seconds of expiry.
|
86
|
+
# Refresh credentials.
|
87
|
+
if @@uploading.length == 0
|
88
|
+
# Wait for all current transfers to complete so we can set a new s3 client.
|
89
|
+
response = refresh_credentials(target, keyPrefix)
|
90
|
+
if response[:success] != true
|
91
|
+
# Must stop upload due to failure to be permitted for new credentials.
|
92
|
+
@@warnings.push(response[:message])
|
93
|
+
break
|
94
|
+
else
|
95
|
+
upload = response[:upload]
|
96
|
+
key = upload['key']
|
97
|
+
upload_message = upload['message']
|
98
|
+
permit = upload['permit']
|
99
|
+
auth = upload['auth']
|
100
|
+
if permit != true
|
101
|
+
# Must stop upload due to failure to be permitted for new credentials.
|
102
|
+
@@warnings.push(upload_message)
|
103
|
+
break
|
104
|
+
else
|
105
|
+
# Upload permitted.
|
106
|
+
expiration_string = auth['Expiration']
|
107
|
+
expiration = expiration_string.to_i
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
if now + @@expire_buffer < expiration
|
114
|
+
# Load new file for upload.
|
115
|
+
f = files.shift
|
116
|
+
if File.file?(f[:file])
|
117
|
+
fname = File.basename f[:file]
|
118
|
+
key = keyPrefix + '/' + f[:num].to_s + '/' + fname
|
119
|
+
@@uploading.push(f[:file])
|
120
|
+
transfer(f[:file], File.size(f[:file]), key, auth)
|
121
|
+
else
|
122
|
+
@@warnings.push('File not found: ' + f[:file])
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Check if existing upload complete - handled by each transfer.
|
128
|
+
rescue => e
|
129
|
+
@@warnings.push(e.message)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
return {:message => '. ' + @@files_uploaded.to_s + ' files uploaded. ' + @@bytes_uploaded.to_s + ' bytes uploaded.', :warnings => @@warnings}
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.files_in_test_cases(data)
|
137
|
+
results = data[:results]
|
138
|
+
cases = results[:cases]
|
139
|
+
files = []
|
140
|
+
num = 0
|
141
|
+
cases.each do |c|
|
142
|
+
c_files = c[:files]
|
143
|
+
if c_files == nil
|
144
|
+
next
|
145
|
+
else
|
146
|
+
c_files.each do |f|
|
147
|
+
files.push({:num => num, :file => f})
|
148
|
+
end
|
149
|
+
end
|
150
|
+
num += 1
|
151
|
+
end
|
152
|
+
return files
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.upload(data)
|
156
|
+
begin
|
157
|
+
uri = URI("https://www.tesults.com/results")
|
158
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
159
|
+
http.use_ssl = true
|
160
|
+
req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
|
161
|
+
req.body = data.to_json
|
162
|
+
res = http.request(req)
|
163
|
+
jsonData = JSON.parse(res.body)
|
164
|
+
success = false
|
165
|
+
message = ""
|
166
|
+
if jsonData['error'] == nil
|
167
|
+
success = true
|
168
|
+
d = jsonData['data']
|
169
|
+
message = d['message']
|
170
|
+
upload = d['upload']
|
171
|
+
|
172
|
+
if upload == nil
|
173
|
+
# No files to upload, complete.
|
174
|
+
val = {:success => success, :message => message, :warnings => [], :errors => []}
|
175
|
+
else
|
176
|
+
# Upload files.
|
177
|
+
target = data[:target]
|
178
|
+
files = files_in_test_cases(data)
|
179
|
+
|
180
|
+
key = upload['key']
|
181
|
+
upload_message = upload['message']
|
182
|
+
permit = upload['permit']
|
183
|
+
auth = upload['auth']
|
184
|
+
|
185
|
+
if permit != true
|
186
|
+
val = {:success => success, :message => message, :warnings => [uploadMessage], :errors => []}
|
187
|
+
else
|
188
|
+
# Upload required and permitted.
|
189
|
+
begin
|
190
|
+
file_upload_return = files_upload(files, key, auth, target) # This can take a while
|
191
|
+
upload_message = file_upload_return[:message]
|
192
|
+
rescue => e
|
193
|
+
@@warnings.push(e.message)
|
194
|
+
upload_message = '. View warnings.'
|
195
|
+
ensure
|
196
|
+
return {:success => success, :message => "Success" + upload_message.to_s, :warnings => @@warnings, :errors => []}
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
else
|
201
|
+
success = false
|
202
|
+
error = jsonData['error']
|
203
|
+
message = error['message']
|
204
|
+
return {:success => success, :message => message, :warnings => [], :errors => [message]}
|
205
|
+
end
|
206
|
+
rescue => e
|
207
|
+
return {:success => false, :message => e.message, :warnings=> [], :errors => [e.message]}
|
208
|
+
end
|
26
209
|
end
|
27
|
-
end
|
210
|
+
end
|
metadata
CHANGED
@@ -1,17 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tesults
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tesults
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
|
11
|
+
date: 2017-04-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Tesults API library for uploading test results to Tesults in your Ruby
|
42
|
+
application.
|
15
43
|
email:
|
16
44
|
- support@tesults.com
|
17
45
|
executables: []
|