s3_meta_sync 0.13.1 → 0.15.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 216269b8e8057ed05a79cfdc52324704203c57e5
4
- data.tar.gz: 924fd0b552fbe6734acb3c89e5cb3193bff08f1d
2
+ SHA256:
3
+ metadata.gz: eb3dcbb8679154cb0863f3c13ba43d5c828220cbc2f0624346c19cf3617dd358
4
+ data.tar.gz: 6973f43e1a0bad829be2748ec65e447a2f7e96c16b2d95746d3bfad1e8daa0ea
5
5
  SHA512:
6
- metadata.gz: 8ea2a75355336b6c88d303ed183d5681819c4d560f3edcde9bdfc1aca872ec690b9032abcd97e8d7c8aba36bd76bf7d2e0924903450512eb61b7642582b23134
7
- data.tar.gz: 0c59e4cfb6a6630f932385e573209f644b39498336ab9fe379a104a579834518eaada8cba94dcccb4e77f910ebc719b3d1bc1779e18b1bd964ef6f64ec83d60f
6
+ metadata.gz: e6aca9b4086bf08b5bb18ea74622fd4ad45fa783440246499459e5d8663b331ab3b63cef7ce2c78a8eb66eb7ae6470e5fffd2beb43ab95363d38f96bf60128b5
7
+ data.tar.gz: d8c6e284debf19ac52094a3ec1e36cb158b318b3c655fbc5a63a9c65ebc236048c24af184327a8085acfe11b082395a53a3e199e654e63cb0ca6195b455e4a8c
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "optparse"
2
4
  require "s3_meta_sync/version"
3
5
  require "s3_meta_sync/syncer"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "net/http"
2
4
  require "open-uri"
3
5
  require "yaml"
@@ -5,17 +7,24 @@ require "digest/md5"
5
7
  require "fileutils"
6
8
  require "tmpdir"
7
9
  require "openssl"
10
+ require "mime/types"
8
11
 
9
- require "aws-sdk-core"
12
+ require "aws-sdk-s3"
10
13
  require "s3_meta_sync/zip"
11
14
 
12
15
  module S3MetaSync
13
16
  class Syncer
14
- DEFAULT_REGION = 'us-east-1'
17
+ DEFAULT_REGION = "us-east-1"
15
18
  STAGING_AREA_PREFIX = "s3ms_"
16
19
 
20
+ AWS_PUBLIC_ACCESS = "public-read"
21
+ AWS_PRIVATE_ACCESS = "private"
22
+
17
23
  def initialize(config)
18
- @config = config
24
+ @config = {
25
+ acl: AWS_PUBLIC_ACCESS,
26
+ region: DEFAULT_REGION
27
+ }.merge(config)
19
28
  end
20
29
 
21
30
  def sync(source, destination)
@@ -93,7 +102,7 @@ module S3MetaSync
93
102
  # Sometimes SIGTERM causes Dir.mktmpdir to not properly delete the temp folder
94
103
  # Remove 1 day old folders
95
104
  def delete_old_temp_folders
96
- path = File.join(Dir.tmpdir, STAGING_AREA_PREFIX + '*')
105
+ path = File.join(Dir.tmpdir, STAGING_AREA_PREFIX + "*")
97
106
 
98
107
  day = 24 * 60 * 60
99
108
  dirs = Dir.glob(path)
@@ -161,10 +170,12 @@ module S3MetaSync
161
170
  content = Zip.zip(content) if @config[:zip] && path != META_FILE
162
171
 
163
172
  object = {
173
+ acl: @config[:acl],
164
174
  bucket: @bucket,
165
175
  body: content,
166
- key: "#{destination}/#{path}",
167
- acl: 'public-read'
176
+ content_encoding: content.encoding.to_s,
177
+ content_type: MIME::Types.of(path).first.to_s,
178
+ key: "#{destination}/#{path}"
168
179
  }
169
180
 
170
181
  object[:server_side_encryption] = @config[:server_side_encryption] if @config[:server_side_encryption]
@@ -195,11 +206,19 @@ module S3MetaSync
195
206
  end
196
207
 
197
208
  def s3
198
- @s3 ||= ::Aws::S3::Client.new(
199
- access_key_id: @config[:key],
200
- secret_access_key: @config[:secret],
201
- region: @config[:region] || 'us-west-2'
202
- )
209
+ @s3 ||= begin
210
+ config = { region: @config[:region] }
211
+
212
+ if @config[:credentials_path]
213
+ config[:credentials] = Aws::SharedCredentials.new(path: @config[:credentials_path], profile_name: "default")
214
+ else
215
+ config[:access_key_id] = @config[:key]
216
+ config[:secret_access_key] = @config[:secret]
217
+ config[:session_token] = @config[:session_token] if @config[:session_token]
218
+ end
219
+
220
+ Aws::S3::Client.new(config)
221
+ end
203
222
  end
204
223
 
205
224
  def generate_meta(source)
@@ -230,21 +249,50 @@ module S3MetaSync
230
249
 
231
250
  def read_meta(source)
232
251
  file = "#{source}/#{META_FILE}"
233
- parse_yaml_content(File.read(file)) if File.exist?(file)
252
+ if File.exist?(file)
253
+ content = File.read(file)
254
+ parse_yaml_content(content) if content.size > 0
255
+ end
234
256
  end
235
257
 
236
258
  def download_meta(destination)
259
+ if private?
260
+ private_access_download_meta(destination)
261
+ else
262
+ public_access_download_meta(destination)
263
+ end
264
+ end
265
+
266
+ def private_access_download_meta(destination)
267
+ content = private_content_download(destination, META_FILE).string
268
+
269
+ raise S3MetaSync::RemoteWithoutMeta if content.empty? # if missing, upload everything
270
+
271
+ parse_yaml_content(content)
272
+ rescue Aws::S3::Errors::NoSuchKey, Aws::S3::Errors::AccessDenied # if requesting a file that doesn't exist AccessDenied is raised
273
+ retries ||= 0
274
+
275
+ raise S3MetaSync::RemoteWithoutMeta if retries >= 1
276
+
277
+ retries += 1
278
+ sleep 1 # maybe the remote meta was just updated ... give aws a second chance ...
279
+ retry
280
+ end
281
+
282
+ def public_access_download_meta(destination)
237
283
  content = download_content("#{destination}/#{META_FILE}") { |io| io.read }
284
+
285
+ raise OpenURI::HTTPError.new("Content is empty", nil) if content.size == 0
286
+
238
287
  parse_yaml_content(content)
239
288
  rescue OpenURI::HTTPError
240
289
  retries ||= 0
290
+
291
+ raise S3MetaSync::RemoteWithoutMeta if retries >= 1
292
+
241
293
  retries += 1
242
- if retries <= 1
243
- sleep 1 # maybe the remote meta was just updated ... give aws a second chance ...
244
- retry
245
- else
246
- raise RemoteWithoutMeta
247
- end
294
+ sleep 1 # maybe the remote meta was just updated ... give aws a second chance ...
295
+ retry
248
296
  end
249
297
 
250
298
  def parse_yaml_content(content)
@@ -253,16 +301,30 @@ module S3MetaSync
253
301
  end
254
302
 
255
303
  def download_file(source, path, destination, zip)
256
- download = download_content("#{source}/#{path}") # warning: using block form consumes more ram
257
- download = Zip.unzip(download) if zip
258
- path = "#{destination}/#{path}"
259
- FileUtils.mkdir_p(File.dirname(path))
304
+ download = if private?
305
+ private_content_download(source, path)
306
+ else
307
+ public_content_download(source, path)
308
+ end
309
+
310
+ download = S3MetaSync::Zip.unzip(download) if zip
311
+ FileUtils.mkdir_p(File.dirname("#{destination}/#{path}"))
260
312
 
261
313
  # consumes less ram then File.write(path, content), possibly also faster
262
- File.open(path, 'wb') { |f| IO.copy_stream(download, f) }
314
+ File.open("#{destination}/#{path}", "wb") { |f| IO.copy_stream(download, f) }
263
315
  download.close
264
316
  end
265
317
 
318
+ def private_content_download(source, path)
319
+ log "Downloading #{path}"
320
+ obj = s3.get_object(bucket: @bucket, key: "#{source}/#{path}")
321
+ obj.body
322
+ end
323
+
324
+ def public_content_download(source, path)
325
+ download_content("#{source}/#{path}") # warning: using block form consumes more ram
326
+ end
327
+
266
328
  def download_content(path)
267
329
  log "Downloading #{path}"
268
330
  url =
@@ -287,8 +349,7 @@ module S3MetaSync
287
349
  log "#{e.class} error downloading #{url}, retrying #{http_error_retries}/#{max_retries}"
288
350
  retry
289
351
  else
290
- $!.message << " -- while trying to download #{url}"
291
- raise
352
+ raise $!, "#{$!.message} -- while trying to download #{url}", $!.backtrace
292
353
  end
293
354
  rescue OpenSSL::SSL::SSLError
294
355
  ssl_error_retries ||= 0
@@ -340,5 +401,9 @@ module S3MetaSync
340
401
  def log(text, important=false)
341
402
  $stderr.puts text if @config[:verbose] or important
342
403
  end
404
+
405
+ def private?
406
+ @config[:acl] == AWS_PRIVATE_ACCESS
407
+ end
343
408
  end
344
409
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module S3MetaSync
2
- VERSION = "0.13.1"
4
+ VERSION = "0.15.2"
3
5
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "zlib"
2
4
  require "stringio"
3
5
 
@@ -5,7 +7,7 @@ module S3MetaSync
5
7
  module Zip
6
8
  class << self
7
9
  def zip(string)
8
- io = StringIO.new("w")
10
+ io = StringIO.new("w".dup)
9
11
  w_gz = Zlib::GzipWriter.new(io)
10
12
  w_gz.write(string)
11
13
  w_gz.close
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3_meta_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.15.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-05 00:00:00.000000000 Z
11
+ date: 2020-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: aws-sdk-core
14
+ name: aws-sdk-s3
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mime-types
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'
27
41
  description:
28
42
  email: michael@grosser.it
29
43
  executables:
@@ -55,8 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
69
  - !ruby/object:Gem::Version
56
70
  version: '0'
57
71
  requirements: []
58
- rubyforge_project:
59
- rubygems_version: 2.4.5.1
72
+ rubygems_version: 3.1.4
60
73
  signing_key:
61
74
  specification_version: 4
62
75
  summary: Sync folders with s3 using a metadata file and md5 diffs