testdroid-api-client 0.2.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +5 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile.lock +65 -37
  5. data/README.md +30 -41
  6. data/lib/testdroid-api-client.rb +25 -9
  7. data/lib/testdroid-api-filter-builder.rb +145 -0
  8. data/lib/testdroid_api/admin.rb +25 -0
  9. data/lib/testdroid_api/admin_device_models.rb +10 -0
  10. data/lib/testdroid_api/admin_device_problems.rb +9 -0
  11. data/lib/testdroid_api/admin_device_statuses.rb +12 -0
  12. data/lib/testdroid_api/admin_devices.rb +10 -0
  13. data/lib/testdroid_api/apikey_client.rb +120 -0
  14. data/lib/testdroid_api/client.rb +158 -123
  15. data/lib/testdroid_api/cloud_list_resource.rb +69 -70
  16. data/lib/testdroid_api/cloud_resource.rb +83 -71
  17. data/lib/testdroid_api/device_groups.rb +9 -9
  18. data/lib/testdroid_api/device_session_connections.rb +10 -0
  19. data/lib/testdroid_api/device_sessions.rb +21 -12
  20. data/lib/testdroid_api/devices.rb +8 -11
  21. data/lib/testdroid_api/files.rb +60 -58
  22. data/lib/testdroid_api/frameworks.rb +11 -0
  23. data/lib/testdroid_api/label_groups.rb +9 -10
  24. data/lib/testdroid_api/labels.rb +9 -10
  25. data/lib/testdroid_api/projects.rb +9 -16
  26. data/lib/testdroid_api/properties.rb +13 -0
  27. data/lib/testdroid_api/runs.rb +22 -12
  28. data/lib/testdroid_api/services.rb +18 -0
  29. data/lib/testdroid_api/user.rb +11 -6
  30. data/sample/BitbarSampleApp.apk +0 -0
  31. data/sample/BitbarSampleAppTest.apk +0 -0
  32. data/sample/sample.rb +23 -23
  33. data/spec/client_spec.rb +7 -7
  34. data/spec/device_groups_spec.rb +30 -17
  35. data/spec/files_spec.rb +40 -20
  36. data/spec/fixtures/apk.apk +0 -0
  37. data/spec/fixtures/cassettes/device_groups_authorize.json +1 -0
  38. data/spec/fixtures/cassettes/device_groups_create.json +1 -0
  39. data/spec/fixtures/cassettes/device_groups_delete.json +1 -0
  40. data/spec/fixtures/cassettes/device_groups_get_all.json +1 -0
  41. data/spec/fixtures/cassettes/device_groups_get_one.json +1 -0
  42. data/spec/fixtures/cassettes/files_authorize.json +1 -0
  43. data/spec/fixtures/cassettes/files_delete.json +1 -0
  44. data/spec/fixtures/cassettes/files_get_all.json +1 -0
  45. data/spec/fixtures/cassettes/files_get_one.json +1 -0
  46. data/spec/fixtures/cassettes/files_upload.json +1 -0
  47. data/spec/fixtures/cassettes/files_upload_with_wait.json +1 -0
  48. data/spec/fixtures/cassettes/label_groups_authorize.json +1 -0
  49. data/spec/fixtures/cassettes/label_groups_create.json +1 -0
  50. data/spec/fixtures/cassettes/label_groups_delete.json +1 -0
  51. data/spec/fixtures/cassettes/label_groups_get_all.json +1 -0
  52. data/spec/fixtures/cassettes/label_groups_get_labels.json +1 -0
  53. data/spec/fixtures/cassettes/label_groups_get_one.json +1 -0
  54. data/spec/fixtures/cassettes/projects_authorize.json +1 -0
  55. data/spec/fixtures/cassettes/projects_create.json +1 -0
  56. data/spec/fixtures/cassettes/projects_delete.json +1 -0
  57. data/spec/fixtures/cassettes/projects_get_all.json +1 -0
  58. data/spec/fixtures/cassettes/projects_get_one.json +1 -0
  59. data/spec/fixtures/cassettes/runs_abort_run.json +1 -0
  60. data/spec/fixtures/cassettes/runs_authorize.json +1 -0
  61. data/spec/fixtures/cassettes/runs_get_project_runs.json +1 -0
  62. data/spec/fixtures/cassettes/runs_start_run.json +1 -0
  63. data/spec/fixtures/data.txt +1 -0
  64. data/spec/fixtures/data2.txt +1 -0
  65. data/spec/label_groups_spec.rb +35 -42
  66. data/spec/projects_spec.rb +41 -0
  67. data/spec/runs_spec.rb +41 -0
  68. data/spec/spec_helper.rb +3 -4
  69. data/testdroid-api-client.gemspec +13 -11
  70. metadata +92 -134
  71. data/lib/testdroid_api/config.rb +0 -7
  72. data/lib/testdroid_api/device_runs.rb +0 -20
  73. data/lib/testdroid_api/file_sets.rb +0 -12
  74. data/spec/device_runs_spec.rb +0 -25
  75. data/spec/file_sets_spec.rb +0 -47
  76. data/spec/fixtures/cassettes/dg_all_device_groups.json +0 -1
  77. data/spec/fixtures/cassettes/dg_device_group_4165.json +0 -1
  78. data/spec/fixtures/cassettes/dg_oauth2_auth_device_groups.json +0 -1
  79. data/spec/fixtures/cassettes/dr_all_run_171221_device_runs.json +0 -1
  80. data/spec/fixtures/cassettes/dr_device_run_33044722.json +0 -1
  81. data/spec/fixtures/cassettes/dr_oauth2_auth_device_runs.json +0 -1
  82. data/spec/fixtures/cassettes/dr_run_33044722_device_runs.json +0 -1
  83. data/spec/fixtures/cassettes/f_add_file_set.json +0 -1
  84. data/spec/fixtures/cassettes/f_android_app_file.json +0 -1
  85. data/spec/fixtures/cassettes/f_file_sets.json +0 -1
  86. data/spec/fixtures/cassettes/f_oauth2_auth_files.json +0 -1
  87. data/spec/fixtures/cassettes/f_upload_files.json +0 -1
  88. data/spec/fixtures/cassettes/fs_add_file_set.json +0 -1
  89. data/spec/fixtures/cassettes/fs_add_file_to_fileset.json +0 -1
  90. data/spec/fixtures/cassettes/fs_delete_file_set.json +0 -1
  91. data/spec/fixtures/cassettes/fs_file_sets.json +0 -1
  92. data/spec/fixtures/cassettes/fs_get_file_set.json +0 -1
  93. data/spec/fixtures/cassettes/fs_oauth2_auth_files.json +0 -1
  94. data/spec/fixtures/cassettes/fs_update_file_set.json +0 -1
  95. data/spec/fixtures/cassettes/fu_oauth2_auth_files.json +0 -1
  96. data/spec/fixtures/cassettes/lg_all_label_groups.json +0 -1
  97. data/spec/fixtures/cassettes/lg_get_resources_by_label.json +0 -1
  98. data/spec/fixtures/cassettes/lg_label_group_1058800.json +0 -1
  99. data/spec/fixtures/cassettes/lg_labels_of_group_1058800.json +0 -1
  100. data/spec/fixtures/cassettes/lg_oauth2_auth_label_groups.json +0 -1
  101. data/spec/fixtures/cassettes/p_all_projects.json +0 -1
  102. data/spec/fixtures/cassettes/p_create_project.json +0 -1
  103. data/spec/fixtures/cassettes/p_get_run_devices.json +0 -1
  104. data/spec/fixtures/cassettes/p_oauth2_auth.json +0 -1
  105. data/spec/fixtures/cassettes/p_oauth2_local.json +0 -1
  106. data/spec/fixtures/cassettes/p_project_id_33029366.json +0 -1
  107. data/spec/fixtures/cassettes/p_run_project.json +0 -1
  108. data/spec/fixtures/cassettes/pc_get_current.json +0 -1
  109. data/spec/fixtures/cassettes/pc_oauth2_auth_config.json +0 -1
  110. data/spec/fixtures/cassettes/pc_set_current_config.json +0 -1
  111. data/spec/fixtures/cassettes/pc_validate_config.json +0 -1
  112. data/spec/fixtures/cassettes/r_all_project_33029366_runs.json +0 -1
  113. data/spec/fixtures/cassettes/r_delete_test_run.json +0 -1
  114. data/spec/fixtures/cassettes/r_oauth2_auth_runs.json +0 -1
  115. data/spec/fixtures/cassettes/r_run_171221.json +0 -1
  116. data/spec/fixtures/cassettes/r_run_project.json +0 -1
  117. data/spec/fixtures/cassettes/upload_files.json +0 -1
  118. data/spec/fixtures/project.json +0 -8
  119. data/spec/project_config_spec.rb +0 -36
  120. data/spec/project_spec.rb +0 -56
  121. data/spec/run_spec.rb +0 -33
@@ -1,83 +1,82 @@
1
-
2
1
  module TestdroidAPI
3
- class CloudListResource
2
+ class CloudListResource
3
+
4
+ def initialize(uri, client, instance_class = nil)
5
+ @uri, @client = uri, client
6
+ resource_name = self.class.name.split('::')[-1]
7
+ @instance_class = TestdroidAPI.const_get(instance_class.nil? ? resource_name.chop : instance_class)
8
+ @list_key, @instance_id_key = resource_name.gsub!(/\b\w/) {$&.downcase}, 'id'
9
+ end
4
10
 
5
- def initialize(uri, client)
6
- @uri, @client = uri, client
7
- resource_name = self.class.name.split('::')[-1]
8
- @instance_class = TestdroidAPI.const_get resource_name.chop
9
- @list_key, @instance_id_key = resource_name.gsub!(/\b\w/) { $&.downcase } , 'id'
10
- end
11
- def get(resource_id)
12
- @instance_class.new( "#{@uri}/#{resource_id}", @client)
13
- end
14
- def total
11
+ def get(resource_id)
12
+ @instance_class.new("#{@uri}/#{resource_id}", @client)
13
+ end
15
14
 
16
- @client.get(@uri)['total']
17
- end
18
- def create(params={})
19
- raise "Can't create a resource without a REST Client" unless @client
20
- response = @client.post @uri, params
21
- @instance_class.new "#{@uri}/#{response[@instance_id_key]}", @client,
22
- response
23
- end
24
- def list_all()
25
- raise "Can't get a resource list without a REST Client" unless @client
15
+ def total
16
+ @client.get(@uri)['total']
17
+ end
26
18
 
27
- response = @client.get("#{@uri}?limit=355043550", {})
19
+ def create(params = {})
20
+ raise "Can't create a resource without a REST Client" unless @client
21
+ response = @client.post @uri, params
22
+ @instance_class.new "#{@uri}/#{response[@instance_id_key]}", @client, response
23
+ end
28
24
 
29
- if response['data'].is_a?(Array)
30
- client = @client
31
- class_list = []
32
- list_class = self.class
33
- instance_uri = @uri
34
- response['data'].each do |val|
25
+ def list_all()
26
+ raise "Can't get a resource list without a REST Client" unless @client
35
27
 
36
- class_list << @instance_class.new( "#{instance_uri}/#{val[@instance_id_key]}", @client, val)
37
- end
38
- end
39
- class_list
40
- end
41
- def list(params={}, full_uri=false)
42
- raise "Can't get a resource list without a REST Client" unless @client
43
- @uri = full_uri ? @uri.split(@client.instance_variable_get(:@cloud_url))[1] : @uri
28
+ response = @client.get(@uri, {:limit => 0})
44
29
 
45
- response = @client.get(@uri, params)
30
+ class_list = []
31
+ if response['data'].is_a?(Array)
32
+ instance_uri = @uri
33
+ response['data'].each do |val|
34
+ class_list << @instance_class.new("#{instance_uri}/#{val[@instance_id_key]}", @client, val)
35
+ end
36
+ end
37
+ class_list
38
+ end
46
39
 
47
- if response['data'].is_a?(Array)
48
- client = @client
49
- class_list = []
50
- list_class = self.class
51
- instance_uri = full_uri ? @uri.split('?')[0] : @uri
52
- response['data'].each do |val|
40
+ def list(params = {}, full_uri = false)
41
+ raise "Can't get a resource list without a REST Client" unless @client
42
+ @uri = full_uri ? @uri.split(@client.instance_variable_get(:@cloud_url))[1] : @uri
43
+ response = @client.get(@uri, params)
44
+ class_list = []
45
+ if response['data'].is_a?(Array)
46
+ client = @client
47
+ list_class = self.class
48
+ instance_uri = full_uri ? @uri.split('?')[0] : @uri
49
+ response['data'].each do |val|
53
50
 
54
- class_list << @instance_class.new( "#{instance_uri}/#{val[@instance_id_key]}", @client, val)
55
- end
56
- class_list.instance_eval do
57
- eigenclass = class << self; self; end
51
+ class_list << @instance_class.new("#{instance_uri}/#{val[@instance_id_key]}", @client, val)
52
+ end
53
+ class_list.instance_eval do
54
+ eigenclass = class << self;
55
+ self;
56
+ end
58
57
 
59
- eigenclass.send :define_method, :offset, &lambda {response['offset']}
60
- eigenclass.send :define_method, :limit, &lambda {response['limit']}
61
- eigenclass.send :define_method, :total, &lambda {response['total']}
62
- eigenclass.send :define_method, :next_page, &lambda {
63
- if response['next']
58
+ eigenclass.send :define_method, :offset, &lambda {response['offset']}
59
+ eigenclass.send :define_method, :limit, &lambda {response['limit']}
60
+ eigenclass.send :define_method, :total, &lambda {response['total']}
61
+ eigenclass.send :define_method, :next_page, &lambda {
62
+ if response['next']
64
63
 
65
- list_class.new(response['next'], client).list({}, true)
66
- else
67
- []
68
- end
69
- }
70
- eigenclass.send :define_method, :previous_page, &lambda {
71
- if response['previous']
64
+ list_class.new(response['next'], client).list({}, true)
65
+ else
66
+ []
67
+ end
68
+ }
69
+ eigenclass.send :define_method, :previous_page, &lambda {
70
+ if response['previous']
72
71
 
73
- list_class.new(response['previous'], client).list({}, true)
74
- else
75
- []
76
- end
77
- }
78
- end
79
- end
80
- class_list
81
- end
82
- end
72
+ list_class.new(response['previous'], client).list({}, true)
73
+ else
74
+ []
75
+ end
76
+ }
77
+ end
78
+ end
79
+ class_list
80
+ end
81
+ end
83
82
  end
@@ -1,77 +1,89 @@
1
-
2
1
  module TestdroidAPI
3
- class CloudResource
4
- def initialize(uri, client, resource_name=nil, params= {})
2
+ class CloudResource
3
+ def initialize(uri, client, resource_name = nil, params = {})
4
+
5
+ @uri, @client, @resource_name = uri, client, resource_name
6
+ set_up_properties_from(params)
7
+ end
8
+
9
+ def inspect # :nodoc:
10
+ "<#{self.class} @uri=#{@uri}>"
11
+ end
12
+
13
+ def sub_items(*items)
14
+ items.each do |item|
15
+ resource = camel_case_it item
16
+ uri = "#{@uri}/#{item.to_s.gsub('_', '-') }"
17
+ resource_class = TestdroidAPI.const_get resource
18
+ new_class = resource_class.new(uri, @client)
19
+ instance_variable_set("@#{item}", new_class)
20
+ end
21
+ self.class.instance_eval {attr_reader *items}
22
+ end
23
+
24
+ def method_missing(method, *args)
25
+ super if @updated
26
+ set_up_properties_from(@client.get(@uri))
27
+ self.send method, *args
28
+ end
29
+
30
+ def update(params = {})
31
+ raise "Can't update a resource without a REST Client" unless @client
32
+ set_up_properties_from(@client.post(@uri, params))
33
+ self
34
+ end
35
+
36
+ def set_up_properties_from(hash)
37
+
38
+ eigenclass = class << self;
39
+ self;
40
+ end
41
+ hash.each do |p, v|
42
+ property = snake_case_it p
43
+
44
+ unless ['uri', 'client', 'updated'].include? property
45
+ eigenclass.send :define_method, property.to_sym, &lambda {v}
46
+ end
47
+ end
48
+ @updated = !hash.keys.empty?
49
+ end
50
+
51
+ def refresh
52
+ raise "Can't refresh a resource without a REST Client" unless @client
53
+ @updated = false
54
+ set_up_properties_from(@client.get(@uri))
55
+ self
56
+ end
57
+
58
+ alias_method :load, :refresh
5
59
 
6
- @uri, @client, @resource_name = uri, client, resource_name
7
- set_up_properties_from( params )
8
- end
9
- def inspect # :nodoc:
10
- "<#{self.class} @uri=#{@uri}>"
11
- end
12
- def sub_items(*items)
13
- items.each do |item|
14
- resource = camel_case_it item
15
- uri = "#{@uri}/#{item.to_s.gsub('_', '-') }"
16
- resource_class = TestdroidAPI.const_get resource
17
- new_class = resource_class.new(uri, @client)
18
- instance_variable_set( "@#{item}", new_class )
19
- end
20
- self.class.instance_eval {attr_reader *items}
21
- end
22
- def method_missing(method, *args)
23
- super if @updated
24
- set_up_properties_from(@client.get(@uri))
25
- self.send method, *args
26
- end
27
- def update(params = {})
28
- raise "Can't update a resource without a REST Client" unless @client
29
- set_up_properties_from(@client.post(@uri, params))
30
- self
31
- end
32
- def set_up_properties_from(hash)
60
+ def download_file(file_resource_name, target_file_name = nil)
61
+ raise "Can't refresh a resource without a REST Client" unless @client
62
+ target_file_name = file_resource_name unless target_file_name
63
+ @client.download("#{@uri}/#{file_resource_name}", target_file_name)
64
+ end
33
65
 
34
- eigenclass = class << self; self; end
35
- hash.each do |p,v|
36
- property = snake_case_it p
66
+ def camel_case_it(something)
67
+ if something.is_a? Hash
68
+ Hash[*something.to_a.map {|a| [camel_case_it(a[0]).to_sym, a[1]]}.flatten]
69
+ else
70
+ something.to_s.split('_').map do |s|
71
+ [s[0, 1].capitalize, s[1..-1]].join
72
+ end.join
73
+ end
74
+ end
37
75
 
38
- unless ['uri', 'client', 'updated'].include? property
39
- eigenclass.send :define_method, property.to_sym, &lambda {v}
40
- end
41
- end
42
- @updated = !hash.keys.empty?
43
- end
76
+ def snake_case_it(something)
77
+ if something.is_a? Hash
78
+ Hash[*something.to_a.map {|pair| [snake_case_it(pair[0]).to_sym, pair[1]]}.flatten]
79
+ else
80
+ something.to_s.gsub(/[A-Z][a-z]*/) {|s| "_#{s.downcase}"}.gsub(/^_/, '')
81
+ end
82
+ end
44
83
 
45
- def refresh
46
- raise "Can't refresh a resource without a REST Client" unless @client
47
- @updated = false
48
- set_up_properties_from(@client.get(@uri))
49
- self
50
- end
51
- def download_file(file_resource_name, target_file_name=nil)
52
- raise "Can't refresh a resource without a REST Client" unless @client
53
- target_file_name = file_resource_name unless target_file_name
54
- @client.download("#{@uri}/#{file_resource_name}", target_file_name)
55
- end
56
- def camel_case_it(something)
57
- if something.is_a? Hash
58
- Hash[*something.to_a.map {|a| [camel_case_it(a[0]).to_sym, a[1]]}.flatten]
59
- else
60
- something.to_s.split('_').map do |s|
61
- [s[0,1].capitalize, s[1..-1]].join
62
- end.join
63
- end
64
- end
65
- def snake_case_it(something)
66
- if something.is_a? Hash
67
- Hash[*something.to_a.map {|pair| [snake_case_it(pair[0]).to_sym, pair[1]]}.flatten]
68
- else
69
- something.to_s.gsub(/[A-Z][a-z]*/) {|s| "_#{s.downcase}"}.gsub(/^_/, '')
70
- end
71
- end
72
- def delete
73
- raise "Can't delete a resource without a REST Client" unless @client
74
- @client.delete(@uri)
75
- end
76
- end
84
+ def delete
85
+ raise "Can't delete a resource without a REST Client" unless @client
86
+ @client.delete(@uri)
87
+ end
88
+ end
77
89
  end
@@ -1,12 +1,12 @@
1
-
2
1
  module TestdroidAPI
3
- class DeviceGroups < CloudListResource
4
- end
5
- class DeviceGroup < CloudResource
6
- def initialize(uri, client, params= {})
7
- super uri, client,"deviceGroup", params
8
- @uri, @client = uri, client
9
- end
2
+ class DeviceGroups < CloudListResource
3
+ end
4
+ class DeviceGroup < CloudResource
5
+ def initialize(uri, client, params = {})
6
+ super uri, client, "deviceGroup", params
7
+ @uri, @client = uri, client
8
+ sub_items :devices
9
+ end
10
10
 
11
- end
11
+ end
12
12
  end
@@ -0,0 +1,10 @@
1
+ module TestdroidAPI
2
+ class DeviceSessionConnections < CloudListResource
3
+ end
4
+ class DeviceSessionConnection < CloudResource
5
+ def initialize(uri, client, params = {})
6
+ super uri, client, "DeviceSessionConnection", params
7
+ @uri, @client = uri, client
8
+ end
9
+ end
10
+ end
@@ -1,14 +1,23 @@
1
-
2
1
  module TestdroidAPI
3
- class DeviceSessions < CloudListResource
4
- end
5
- class DeviceSession < CloudResource
6
- def initialize(uri, client, params= {})
7
- super uri, client,"deviceSession", params
8
- @uri, @client = uri, client
9
- end
10
- def release
11
- resp = @client.post("#{@uri}/release", params= {})
12
- end
13
- end
2
+ class DeviceSessions < CloudListResource
3
+ end
4
+ class DeviceSession < CloudResource
5
+ def initialize(uri, client, params = {})
6
+ super uri, client, "deviceSession", params
7
+ @uri, @client = uri, client
8
+ end
9
+
10
+ def release
11
+ @client.post("#{@uri}/release", params = {})
12
+ end
13
+
14
+ def download_all_files(path)
15
+ Dir.mkdir(path) unless Dir.exist?(path)
16
+ files = @client.get("#{@uri}/output-file-set/files")
17
+ files['data'].each do |file|
18
+ @client.download(file['directUrl'], ::File.join(path, "#{file['id']}-#{file['name']}"))
19
+ end
20
+ end
21
+
22
+ end
14
23
  end
@@ -1,13 +1,10 @@
1
-
2
1
  module TestdroidAPI
3
- class Devices < CloudListResource
4
- end
5
- class Device < CloudResource
6
- def initialize(uri, client, params= {})
7
- super uri, client,"device", params
8
- @uri, @client = uri, client
9
-
10
- end
11
-
12
- end
2
+ class Devices < CloudListResource
3
+ end
4
+ class Device < CloudResource
5
+ def initialize(uri, client, params = {})
6
+ super uri, client, "device", params
7
+ @uri, @client = uri, client
8
+ end
9
+ end
13
10
  end
@@ -1,60 +1,62 @@
1
-
2
1
  module TestdroidAPI
3
- class Files < CloudResource
4
- def initialize(uri, client, params= {})
5
-
6
- super uri, client,"files", params
7
- @uri, @client = uri, client
8
-
9
- end
10
-
11
- def uploadApplication(filename, mime_type = "application/vnd.android.package-archive")
12
- if !File.exist?(filename)
13
- @client.logger.error( "Invalid filename")
14
- return
15
- end
16
- reply = @client.upload("#{@uri}/application", filename, mime_type)
17
-
18
- Application.new(nil, nil, reply)
19
- end
20
- def uploadData(filename, mime_type = "application/zip")
21
- if !File.exist?(filename)
22
- @client.logger.error( "Invalid filename")
23
- return
24
- end
25
- reply = @client.upload("#{@uri}/data", filename, mime_type)
26
-
27
- Data.new(nil, nil, reply)
28
- end
29
- def uploadTest(filename, mime_type = "application/vnd.android.package-archive")
30
- if !File.exist?(filename)
31
- @client.logger.error( "Invalid filename")
32
- return
33
- end
34
- reply = @client.upload("#{@uri}/test", filename, mime_type)
35
-
36
- Test.new(nil, nil, reply)
37
- end
38
- end
39
- class Application < CloudResource
40
- def initialize(uri, client, params= {})
41
- super uri, client,"app", params
42
- @uri, @client = uri, client
43
-
44
- end
45
- end
46
- class Test < CloudResource
47
- def initialize(uri, client, params= {})
48
- super uri, client,"test", params
49
- @uri, @client = uri, client
50
-
51
- end
52
- end
53
- class Data < CloudResource
54
- def initialize(uri, client, params= {})
55
- super uri, client,"data", params
56
- @uri, @client = uri, client
57
-
58
- end
59
- end
2
+ class Files < CloudListResource
3
+
4
+ ACCEPTED_VIRUS_SCAN_STATUSES = Set['safe', 'disabled', nil]
5
+
6
+ def upload(filename, skip_scan_wait=false)
7
+ unless ::File.exist?(filename)
8
+ @client.logger.error("Invalid filename")
9
+ return
10
+ end
11
+ file = @client.upload("#{@uri}", filename)
12
+ result = File.new("#{@uri}/#{file['id']}", @client, file)
13
+ if !skip_scan_wait
14
+ wait_for_virus_scan(Array(result))
15
+ end
16
+ return result
17
+ end
18
+
19
+ def wait_for_virus_scan(api_files, timeout=300)
20
+ all_safe = false
21
+ begin
22
+ Timeout.timeout(timeout) do
23
+ while !all_safe do
24
+ statuses = Set.new
25
+ api_files.each do |file|
26
+ current_status = get_virus_scan_status(file)
27
+ if ACCEPTED_VIRUS_SCAN_STATUSES.include?(current_status)
28
+ statuses.add(current_status)
29
+ else
30
+ sleep(1)
31
+ file.refresh
32
+ statuses.add(get_virus_scan_status(file))
33
+ end
34
+ end
35
+ if statuses.include?('infected')
36
+ raise 'File rejected by virus scan'
37
+ end
38
+ if ACCEPTED_VIRUS_SCAN_STATUSES.superset?(statuses)
39
+ all_safe = true
40
+ end
41
+ end
42
+ end
43
+ rescue Timeout::Error
44
+ @client.logger.error("Waiting for virus scan timed out")
45
+ raise
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def get_virus_scan_status(file)
52
+ return file.file_properties.find{ |item| item['key'] == "virus_scan_status" }['value']
53
+ end
54
+ end
55
+
56
+ class File < CloudResource
57
+ def initialize(uri, client, params = {})
58
+ super uri, client, "file", params
59
+ @uri, @client = uri, client
60
+ end
61
+ end
60
62
  end