bucket_client 0.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.
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