testdroid-api-client 0.2.2 → 0.5.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 (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