bucket_client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.gitlab-ci.yml +70 -0
  4. data/.idea/bucket_client.iml +105 -0
  5. data/.idea/encodings.xml +4 -0
  6. data/.idea/misc.xml +7 -0
  7. data/.idea/modules.xml +8 -0
  8. data/.idea/runConfigurations/Integration_Test.xml +37 -0
  9. data/.idea/runConfigurations/Unit_Test.xml +37 -0
  10. data/.rspec +3 -0
  11. data/CODE_OF_CONDUCT.md +74 -0
  12. data/Gemfile +6 -0
  13. data/Gemfile.lock +114 -0
  14. data/LICENSE.txt +21 -0
  15. data/README.md +870 -0
  16. data/Rakefile +6 -0
  17. data/bin/console +14 -0
  18. data/bin/setup +8 -0
  19. data/bucket_client.gemspec +46 -0
  20. data/integration/aws_blob_spec.rb +134 -0
  21. data/integration/aws_bucket_spec.rb +145 -0
  22. data/integration/azure_blob_spec.rb +132 -0
  23. data/integration/azure_bucket_spec.rb +132 -0
  24. data/integration/dev_blob_spec.rb +131 -0
  25. data/integration/dev_bucket_spec.rb +140 -0
  26. data/integration/do_blob_spec.rb +134 -0
  27. data/integration/do_bucket_spec.rb +144 -0
  28. data/integration/gcp_blob_spec.rb +132 -0
  29. data/integration/gcp_bucket_spec.rb +132 -0
  30. data/integration/img.jpg +0 -0
  31. data/lib/bucket_client.rb +66 -0
  32. data/lib/bucket_client/aws/aws_bucket.rb +85 -0
  33. data/lib/bucket_client/aws/aws_client.rb +195 -0
  34. data/lib/bucket_client/aws/aws_http_client.rb +32 -0
  35. data/lib/bucket_client/aws/aws_policy_factory.rb +26 -0
  36. data/lib/bucket_client/aws4_request_signer.rb +133 -0
  37. data/lib/bucket_client/azure/azure_bucket.rb +83 -0
  38. data/lib/bucket_client/azure/azure_client.rb +197 -0
  39. data/lib/bucket_client/bucket.rb +388 -0
  40. data/lib/bucket_client/bucket_operation_exception.rb +8 -0
  41. data/lib/bucket_client/client.rb +408 -0
  42. data/lib/bucket_client/dev/local_bucket.rb +84 -0
  43. data/lib/bucket_client/dev/local_client.rb +148 -0
  44. data/lib/bucket_client/digital_ocean/digital_ocean_acl_factory.rb +39 -0
  45. data/lib/bucket_client/digital_ocean/digital_ocean_bucket.rb +81 -0
  46. data/lib/bucket_client/digital_ocean/digital_ocean_client.rb +275 -0
  47. data/lib/bucket_client/digital_ocean/digital_ocean_http_client.rb +31 -0
  48. data/lib/bucket_client/gcp/gcp_bucket.rb +79 -0
  49. data/lib/bucket_client/gcp/gcp_client.rb +171 -0
  50. data/lib/bucket_client/operation_result.rb +33 -0
  51. data/lib/bucket_client/version.rb +3 -0
  52. metadata +246 -0
@@ -0,0 +1,8 @@
1
+ class BucketOperationException < StandardError
2
+
3
+ # Create a BucketOperationException
4
+ # @param [OperationResult] result the operation that failed
5
+ def initialize(result)
6
+ super("Bucket Operation failed: #{result.message}. Status Code: #{result.code}")
7
+ end
8
+ end
@@ -0,0 +1,408 @@
1
+ module BucketClient
2
+ module BucketMethods
3
+ # Check if bucket exist
4
+ # Throws exception if the HTTP request fails
5
+ #
6
+ # exist = client.exist_bucket("folder") # => true (if bucket exist)
7
+ # exist = client.exist_bucket("folder") #=> false (if bucket does not exist)
8
+ #
9
+ # @param [String] key the bucket name or id
10
+ # @return [Boolean]
11
+ def exist_bucket(key)
12
+ raise NotImplementedError key
13
+ end
14
+
15
+ # Creates a bucket
16
+ # Fails if bucket already exist
17
+ #
18
+ # result = client.create_bucket "folder"
19
+ # result.success #=> Whether the operation succeeded
20
+ # result.code #=> Status Code of the operation
21
+ # result.message #=> Error message if it failed
22
+ # result.value #=> the bucket instance
23
+ #
24
+ # @param [String] key the bucket name or id
25
+ # @return [OperationResult]
26
+ def create_bucket(key)
27
+ raise NotImplementedError key
28
+ end
29
+
30
+ # Creates a bucket
31
+ # Fails if bucket already exist
32
+ #
33
+ # Raises exception if the operation failed
34
+ #
35
+ # bucket = client.create_bucket!("folder_name")
36
+ # bucket #=> Bucket Instance
37
+ #
38
+ # @param [String] key the bucket name or id
39
+ # @return [Bucket]
40
+ def create_bucket!(key)
41
+ result = create_bucket key
42
+ raise BucketOperationException.new(result) unless result.success
43
+ result.value
44
+ end
45
+
46
+ # Deletes a bucket
47
+ # Fails if the bucket does not exist
48
+ #
49
+ # result = client.delete_bucket "folder"
50
+ # result.success #=> Whether the operation succeeded
51
+ # result.code #=> Status Code of the operation
52
+ # result.message #=> Error message if it failed
53
+ # result.value #=> nil
54
+ #
55
+ # @param [String] key the bucket name or id
56
+ # @return [OperationResult]
57
+ def delete_bucket(key)
58
+ raise NotImplementedError key
59
+ end
60
+
61
+ # Deletes a bucket
62
+ # Fails if the bucket does not exist
63
+ # Raises error if it operation fails
64
+ #
65
+ # client.delete_bucket! "folder"
66
+ #
67
+ # @param [String] key the bucket name or id
68
+ def delete_bucket!(key)
69
+ result = delete_bucket key
70
+ raise BucketOperationException.new(result) unless result.success
71
+ end
72
+
73
+ # Sets the read policy of the bucket
74
+ # Fails if bucket does not exist
75
+ #
76
+ # Raises exception if neither :public nor :private is provided.
77
+ #
78
+ # result = client.set_read_policy :public #=> Sets read policy to public
79
+ # result_2 = client.set_read_policy :private #=> Sets read policy to private
80
+ #
81
+ # result.success #=> Whether the operation succeeded
82
+ # result.code #=> Status Code of the operation
83
+ # result.message #=> Error message if it failed
84
+ # result.value #=> nil
85
+ #
86
+ # @param [String] key the bucket name or id
87
+ # @param [Symbol] access :public or :private
88
+ # @return [OperationResult]
89
+ def set_read_policy(key, access)
90
+ raise NotImplementedError key + access
91
+ end
92
+
93
+ # Sets the read policy of the bucket
94
+ # Fails if bucket does not exist
95
+ #
96
+ # Raises exception if neither :public nor :private is provided.
97
+ # Raises exception if the operation fails
98
+ #
99
+ # client.set_read_policy! :public #=> Sets read policy to public
100
+ # client.set_read_policy! :private #=> Sets read policy to private
101
+ #
102
+ # @param [String] key the bucket name or id
103
+ # @param [Symbol] access :public or :private
104
+ def set_read_policy!(key, access)
105
+ result = set_read_policy key, access
106
+ raise BucketOperationException.new(result) unless result.success
107
+ end
108
+
109
+ # Sets the GET CORS for the bucket
110
+ # Fails if bucket does not exist
111
+ #
112
+ # result = client.set_get_cors "folder", ["domain2.net","domain1.net"]
113
+ # result.success #=> Whether the operation succeeded
114
+ # result.code #=> Status Code of the operation
115
+ # result.message #=> Error message if it failed
116
+ # result.value #=> nil
117
+ #
118
+ # @param [String] key the bucket name or id
119
+ # @param [Array<String>] cors Array of CORS to allow GET requests
120
+ # @return [OperationResult]
121
+ def set_get_cors(key, cors)
122
+ throw new NotImplementedError key + cors.to_s
123
+ end
124
+
125
+ # Sets the GET CORS for the bucket
126
+ # Fails if bucket does not exist
127
+ #
128
+ # Raises exception if operation fails
129
+ #
130
+ # client.set_get_cors! "folder", ["domain2.net","domain1.net"]
131
+ #
132
+ # @param [String] key the bucket name or id
133
+ # @param [Array<String>] cors Array of CORS to allow GET requests
134
+ def set_get_cors!(key, cors)
135
+ result = set_get_cors key, cors
136
+ raise BucketOperationException.new(result) unless result.success
137
+ end
138
+
139
+ # Creates the bucket if it does not exist
140
+ #
141
+ # result = client.put_bucket "folder"
142
+ # result.success #=> Whether the operation succeeded
143
+ # result.code #=> Status Code of the operation
144
+ # result.message #=> Error message if it failed
145
+ # result.value #=> bucket instance
146
+ #
147
+ # @param [String] key the bucket name or id
148
+ # @return [OperationResult]
149
+ def put_bucket(key)
150
+ raise NotImplementedError key
151
+ end
152
+
153
+ # Creates the bucket if it does not exist
154
+ #
155
+ # Raises exception if the operation fails
156
+ #
157
+ # bucket = client.put_bucket "folder"! #=> Bucket if succeeds
158
+ #
159
+ # @param [String] key the bucket name or id
160
+ # @return [Bucket]
161
+ def put_bucket!(key)
162
+ result = put_bucket key
163
+ raise BucketOperationException.new(result) unless result.success
164
+ result.value
165
+ end
166
+
167
+ # Delete the bucket if it exist
168
+ #
169
+ # result = client.delete_bucket_if_exist "folder"
170
+ # result.success #=> Whether the operation succeeded
171
+ # result.code #=> Status Code of the operation
172
+ # result.message #=> Error message if it failed
173
+ # bucket.value #=> nil
174
+ #
175
+ # @param [String] key the bucket name or id
176
+ # @return [OperationResult]
177
+ def delete_bucket_if_exist(key)
178
+ raise NotImplementedError key
179
+ end
180
+
181
+ # Delete the bucket if it exist
182
+ #
183
+ # Raises exception if operations fails
184
+ #
185
+ # client.delete_bucket_if_exist! "folder"
186
+ #
187
+ # @param [String] key the bucket name or id
188
+ def delete_bucket_if_exist!(key)
189
+ result = delete_bucket key
190
+ raise BucketOperationException.new(result) unless result.success
191
+ end
192
+
193
+ # Gets the instance of the bucket.
194
+ #
195
+ # Checks whether the bucket exist and returns a Bucket Instance to interact
196
+ # with the bucket if it does.
197
+ #
198
+ # Raises exception if bucket does not exist
199
+ #
200
+ # bucket = client.get_bucket "folder" #=> Gets bucket instance of it exist
201
+ #
202
+ # @param [String] key the bucket name or id
203
+ # @return [Bucket]
204
+ def get_bucket(key)
205
+ exist = exist_bucket key
206
+ result = OperationResult.new(false, "Bucket does not exist", nil, 404)
207
+ raise BucketOperationException.new(result) unless exist
208
+ get_bucket! key
209
+ end
210
+
211
+ # Gets the instance of the bucket
212
+ # Does not check whether the bucket exist or not. Simply generates a bucket instance
213
+ # optimistically. This operation is non-block as compared to get_bucket as it does
214
+ # not send out a HTTP request to check if the bucket exist.
215
+ #
216
+ # However, the bucket will not work (raise exception) if the bucket does not exist
217
+ # when you use the instance. Use this method only when you are sure that the bucket
218
+ # exist.
219
+ #
220
+ # bucket = client.get_bucket! "folder"
221
+ #
222
+ # @param [String] key the bucket name or id
223
+ # @return [Bucket]
224
+ def get_bucket!(key)
225
+ raise NotImplementedError key
226
+ end
227
+ end
228
+
229
+ module BlobMethods
230
+ # Gets the blob in the target URL as byte array.
231
+ #
232
+ # blob = client.get_blob "https://host.com/bucket"
233
+ # result.success #=> Whether the operation succeeded
234
+ # result.code #=> Status Code of the operation
235
+ # result.message #=> Error message if it failed
236
+ # result.value #=> Byte array (payload of blob)
237
+ #
238
+ # @param [String] uri the endpoint of the blob you want to get
239
+ # @return [OperationResult]
240
+ def get_blob(uri)
241
+ raise NotImplementedError uri
242
+ end
243
+
244
+ # Gets the blob in the target URL as byte array
245
+ #
246
+ # Raises exception if operation fails
247
+ #
248
+ # blob = client.get_blob! "https://host.com/bucket" #=> [12,65,127,33] (some byte array)
249
+ #
250
+ # @param [String] uri the endpoint of the blob you want to get
251
+ # @return [Array<Byte>]
252
+ def get_blob!(uri)
253
+ result = get_blob(uri)
254
+ raise BucketOperationException.new(result) unless result.success
255
+ result.value
256
+ end
257
+
258
+ # Check if blob with URI exist#
259
+ #
260
+ # Raises exception when the operation fails
261
+ #
262
+ # exist = exist_blob "https://host.com/folder/blob.ext"
263
+ # exist #=> true if exist, false if does not exist
264
+ #
265
+ # @param [String] uri the URL of the blob
266
+ # @return [Boolean]
267
+ def exist_blob(uri)
268
+ raise NotImplementedError uri
269
+ end
270
+
271
+ # Updates a blob with new payload in byte array
272
+ # Fails if blob with the URI doesn't exist
273
+ #
274
+ # img = IO.binread "pic.png"
275
+ # uri = "https://host.com/folder/pic.png"
276
+ # result = client.update_blob img, uri
277
+ # result.success #=> Whether the operation succeeded
278
+ # result.code #=> Status Code of the operation
279
+ # result.message #=> Error message if it failed
280
+ # result.value #=> Uri of update blob
281
+ #
282
+ # @param [Array<Byte>] payload the payload to update the blob
283
+ # @param [String] uri the URL of the blob
284
+ # @return [OperationResult]
285
+ def update_blob(payload, uri)
286
+ raise NotImplementedError payload.to_s + uri
287
+ end
288
+
289
+ # Updates a blob with new payload in byte array
290
+ # Fails if blob doesnt exist
291
+ #
292
+ # Raises exception if operation fails
293
+ #
294
+ # img = IO.binread "pic.png"
295
+ # uri = "https://host.com/folder/pic.png"
296
+ # result = client.update_blob! img, uri #=> URI of update blob
297
+ #
298
+ # @param [Array<Byte>] payload the payload to update the blob
299
+ # @param [String] uri the URL of the blob
300
+ def update_blob!(payload, uri)
301
+ result = update_blob payload, uri
302
+ raise BucketOperationException.new(result) unless result.success
303
+ result.value
304
+ end
305
+
306
+ # Creates the blob with the payload if it does not exist,
307
+ # Updates the blob with the new payload if it exist
308
+ #
309
+ # img = IO.binread "pic.png"
310
+ # uri = "https://host.com/folder/pic.png"
311
+ # result = client.put_blob img, uri
312
+ # result.success #=> Whether the operation succeeded
313
+ # result.code #=> Status Code of the operation
314
+ # result.message #=> Error message if it failed
315
+ # result.value #=> Uri of blob
316
+ #
317
+ # @param [Array<Byte>] payload the payload to put
318
+ # @param [String] uri the URL of the blob
319
+ # @return [OperationResult]
320
+ def put_blob(payload, uri)
321
+ raise NotImplementedError payload.to_s + uri
322
+ end
323
+
324
+ # Creates the blob with the payload if it does not exist,
325
+ # Updates the blob with the new payload if it exist
326
+ #
327
+ # Raises exception if the operation fails
328
+ #
329
+ # img = IO.binread "pic.png"
330
+ # uri = "https://host.com/folder/pic.png"
331
+ # result = client.put_blob!(img,uri) #=> returns URI of updated blob
332
+ #
333
+ # @param [Array<Byte>] payload the payload to put
334
+ # @param [String] uri the URL of the blob
335
+ # @return [String]
336
+ def put_blob!(payload, uri)
337
+ result = put_blob payload, uri
338
+ raise NotImplementedError result unless result.success
339
+ result.value
340
+ end
341
+
342
+ # Deletes the blob in the provided URI
343
+ # Fails if the blob does not exist. Use delete_blob_if_exist if you
344
+ # do not want this behaviour
345
+ #
346
+ # uri = "https://host.com/folder/pic.png"
347
+ # result = client.delete_blob uri
348
+ # result.success #=> Whether the operation succeeded
349
+ # result.code #=> Status Code of the operation
350
+ # result.message #=> Error message if it failed
351
+ # result.value #=> nil
352
+ #
353
+ # @param [String] uri the URL of the blob
354
+ # @return [OperationResult]
355
+ def delete_blob(uri)
356
+ raise NotImplementedError uri
357
+ end
358
+
359
+ # Deletes the blob in the provided URI
360
+ # Fails if the blob does not exist. Use delete_blob_if_exist if you
361
+ # do not want this behaviour
362
+ #
363
+ # Raises exception if the operation fails
364
+ #
365
+ # uri = "https://host.com/folder/pic.png"
366
+ # client.delete_blob! uri
367
+ #
368
+ # @param [String] uri URL of the blob
369
+ def delete_blob!(uri)
370
+ result = delete_blob uri
371
+ raise BucketOperationException.new(result) unless result.success
372
+ end
373
+
374
+ # Deletes the blob if it exist, else does nothing
375
+ #
376
+ # uri = "https://host.com/folder/pic.png"
377
+ # result = client.delete_blob uri
378
+ # result.success #=> Whether the operation succeeded
379
+ # result.code #=> Status Code of the operation
380
+ # result.message #=> Error message if it failed
381
+ # result.value #=> nil
382
+ #
383
+ # @param [String] uri the URL of the blob
384
+ # @return [OperationResult]
385
+ def delete_blob_if_exist(uri)
386
+ raise NotImplementedError uri
387
+ end
388
+
389
+ # Deletes the blob if it exist, else does nothing
390
+ #
391
+ # Raises exception if the operation fails
392
+ #
393
+ # uri = "https://host.com/folder/pic.png"
394
+ # client.delete_blob! uri
395
+ #
396
+ # @param [String] uri the URL of the blob
397
+ def delete_blob_if_exist!(uri)
398
+ result = delete_blob_if_exist uri
399
+ raise BucketOperationException.new(result) unless result.success
400
+ end
401
+
402
+ end
403
+
404
+ # Client to interact with Storage service. Ability to perform Bucket CRUD
405
+ class Client
406
+ include BucketMethods, BlobMethods
407
+ end
408
+ end
@@ -0,0 +1,84 @@
1
+ module BucketClient
2
+ class LocalBucket < Bucket
3
+ attr_reader :key
4
+
5
+ def initialize(parent, key)
6
+ @key = key
7
+ @bucket_client = parent
8
+ end
9
+
10
+ def get_uri(key)
11
+ combine @bucket_client.principal, @key, key
12
+ end
13
+
14
+ def get_blob_with_uri(uri)
15
+ @bucket_client.get_blob uri
16
+ end
17
+
18
+ def exist_blob_with_uri(uri)
19
+ @bucket_client.exist_blob(uri)
20
+ end
21
+
22
+ def put_blob_with_uri(payload, uri)
23
+ @bucket_client.put_blob payload, uri
24
+ end
25
+
26
+ def update_blob_with_uri(payload, uri)
27
+ exist = exist_blob_with_uri uri
28
+ if exist
29
+ put_blob_with_uri payload, uri
30
+ else
31
+ OperationResult.new false, "Blob does not exist", nil, 400
32
+ end
33
+ end
34
+
35
+ def delete_blob_with_uri(uri)
36
+ @bucket_client.delete_blob(uri)
37
+ end
38
+
39
+ def delete_blob_if_exist_with_uri(uri)
40
+ @bucket_client.delete_blob_if_exist(uri)
41
+ end
42
+
43
+ def get_blob(key)
44
+ get_blob_with_uri(get_uri key)
45
+ end
46
+
47
+ def exist_blob(key)
48
+ exist_blob_with_uri(get_uri key)
49
+ end
50
+
51
+ def put_blob(payload, key)
52
+ put_blob_with_uri(payload, get_uri(key))
53
+ end
54
+
55
+ def create_blob(payload, key)
56
+ exist = exist_blob key
57
+ if exist
58
+ OperationResult.new false, "Blob already exist", nil, 400
59
+ else
60
+ put_blob payload, key
61
+ end
62
+ end
63
+
64
+ def update_blob(payload, key)
65
+ update_blob_with_uri(payload, get_uri(key))
66
+ end
67
+
68
+ def delete_blob(key)
69
+ delete_blob_with_uri(get_uri key)
70
+ end
71
+
72
+ def delete_blob_if_exist(key)
73
+ delete_blob_if_exist_with_uri(get_uri key)
74
+ end
75
+
76
+ private
77
+
78
+ def combine(*args)
79
+ Pathname.new(File.join(args)).cleanpath.to_s
80
+ end
81
+
82
+
83
+ end
84
+ end