bfs-s3 0.8.0 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e4e2d75bba619dbe3e7a68ff669b91cb5e031acbac453683f6197d11a7cc98d
4
- data.tar.gz: 1b92cdd4b1cf3bfbd2b173498de47d7b27528f590010fe5ab5256f6bd391d373
3
+ metadata.gz: 4d6df20270797fc308401a911b078872076ce9cb248bec9fd7c725fec0d034a3
4
+ data.tar.gz: 27cc25f8e2d2f4a854d83decf3fffdff7771c67b9bd69c41d87f0b23a79903fd
5
5
  SHA512:
6
- metadata.gz: d5848551c6fe1b2cc699c3d0cdb47010e2806296cc3cb7734c8a40ede206b566d49855110e70fca2917b65cd92f943497e6acec00b6c17713f3f7a04efb7142d
7
- data.tar.gz: 4e410ead67a7cf7886b14224d216311f759f1be92dc42d85e4ccf11772c935e22fbd723db3f26274f729ac445b15cb56f847c76fa3444799e5d80b7e9cfed398
6
+ metadata.gz: 3c370605ebd6d535da63e198dfc5141e7343eb1b3a55ee3d34c9714d7a83157d2a922089cc875f84b369e6e87181849c1a3ab3ec22b35bcda168614329cfa982
7
+ data.tar.gz: ad263a8e5ee1c2e6423d476b7a65b7d2d227a39002c6d495d8d672bdb22a909bc50c802b306e6ef1a2c7f45ba45246fe24de7daf070a26524319b05f4da07dd9
data/lib/bfs/bucket/s3.rb CHANGED
@@ -33,22 +33,19 @@ module BFS
33
33
 
34
34
  # Lists the contents of a bucket using a glob pattern
35
35
  def ls(pattern = '**/*', **opts)
36
- prefix = pattern[%r{^[^*?\{\}\[\]]+/}]
37
- prefix = File.join(*[@prefix, prefix].compact) if @prefix
38
-
39
- opts = opts.merge(bucket: name, prefix: @prefix)
40
- opts[:prefix] = prefix if prefix
36
+ Enumerator.new do |acc|
37
+ walk(pattern, **opts) do |path, _|
38
+ acc << path
39
+ end
40
+ end
41
+ end
41
42
 
42
- next_token = nil
43
- Enumerator.new do |y|
44
- loop do
45
- resp = @client.list_objects_v2 opts.merge(continuation_token: next_token)
46
- resp.contents.each do |obj|
47
- name = trim_prefix(obj.key)
48
- y << name if File.fnmatch?(pattern, name, File::FNM_PATHNAME)
49
- end
50
- next_token = resp.next_continuation_token.to_s
51
- break if next_token.empty?
43
+ # Iterates over the contents of a bucket using a glob pattern
44
+ def glob(pattern = '**/*', **opts)
45
+ Enumerator.new do |acc|
46
+ walk(pattern, **opts) do |path, obj|
47
+ info = BFS::FileInfo.new(path: path, size: obj.size, mtime: obj.last_modified)
48
+ acc << info
52
49
  end
53
50
  end
54
51
  end
@@ -60,7 +57,7 @@ module BFS
60
57
  info = @client.head_object(**opts)
61
58
  raise BFS::FileNotFound, path unless info
62
59
 
63
- BFS::FileInfo.new(path: path, size: info.content_length, mtime: info.last_modified, content_type: info.content_type, metadata: norm_meta(info.metadata))
60
+ BFS::FileInfo.new path: path, size: info.content_length, mtime: info.last_modified, content_type: info.content_type, metadata: norm_meta(info.metadata)
64
61
  rescue Aws::S3::Errors::NoSuchKey, Aws::S3::Errors::NoSuchBucket, Aws::S3::Errors::NotFound
65
62
  raise BFS::FileNotFound, path
66
63
  end
@@ -144,9 +141,38 @@ module BFS
144
141
  config[:credentials] = opts[:credentials] if opts[:credentials]
145
142
  config[:credentials] ||= Aws::Credentials.new(opts[:access_key_id].to_s, opts[:secret_access_key].to_s) if opts[:access_key_id]
146
143
  config[:credentials] ||= Aws::SharedCredentials.new(profile_name: opts[:profile_name]) if opts[:profile_name]
144
+ config[:credentials] = assume_role_credentials(opts[:assume_role], config[:credentials]) if opts[:assume_role]
147
145
 
148
146
  Aws::S3::Client.new(config)
149
147
  end
148
+
149
+ def assume_role_credentials(role_arn, credentials = nil)
150
+ opts = {
151
+ role_arn: role_arn,
152
+ role_session_name: SecureRandom.urlsafe_base64(12),
153
+ }
154
+ opts[:client] = Aws::STS::Client.new(credentials: credentials) if credentials
155
+ Aws::AssumeRoleCredentials.new(**opts)
156
+ end
157
+
158
+ def walk(pattern, **opts)
159
+ prefix = pattern[%r{^[^*?\{\}\[\]]+/}]
160
+ prefix = File.join(*[@prefix, prefix].compact) if @prefix
161
+
162
+ opts = opts.merge(bucket: name, prefix: @prefix)
163
+ opts[:prefix] = prefix if prefix
164
+
165
+ next_token = nil
166
+ loop do
167
+ resp = @client.list_objects_v2 opts.merge(continuation_token: next_token)
168
+ resp.contents.each do |obj|
169
+ path = trim_prefix(obj.key)
170
+ yield(path, obj) if File.fnmatch?(pattern, path, File::FNM_PATHNAME)
171
+ end
172
+ next_token = resp.next_continuation_token.to_s
173
+ break if next_token.empty?
174
+ end
175
+ end
150
176
  end
151
177
  end
152
178
  end
@@ -154,7 +180,7 @@ end
154
180
  BFS.register('s3') do |url, opts, block|
155
181
  prefix = BFS.norm_path(opts[:prefix] || url.path)
156
182
  opts[:prefix] = prefix.empty? ? nil : prefix
157
- opts = opts.slice(:prefix, :region, :sse, :access_key_id, :secret_access_key, :acl, :storage_class, :encoding)
183
+ opts = opts.slice(:prefix, :region, :sse, :access_key_id, :secret_access_key, :acl, :storage_class, :encoding, :assume_role)
158
184
 
159
185
  BFS::Bucket::S3.open url.host, **opts, &block
160
186
  end
@@ -3,20 +3,20 @@ require 'spec_helper'
3
3
  bucket_name = 'bsm-bfs-unittest'
4
4
 
5
5
  RSpec.describe BFS::Bucket::S3, s3: true do
6
- let(:prefix) { "x/#{SecureRandom.uuid}/" }
7
-
8
6
  subject do
9
7
  described_class.new bucket_name, prefix: prefix
10
8
  end
11
9
 
12
- after :all do
13
- bucket = described_class.new bucket_name, prefix: 'x/'
10
+ let(:prefix) { "x/#{SecureRandom.uuid}/" }
11
+
12
+ after do
13
+ bucket = described_class.new bucket_name, prefix: prefix
14
14
  bucket.ls.each {|name| bucket.rm(name) }
15
15
  end
16
16
 
17
17
  it_behaves_like 'a bucket'
18
18
 
19
- it 'should resolve from URL' do
19
+ it 'resolves from URL' do
20
20
  bucket = BFS.resolve("s3://#{bucket_name}/?acl=private&encoding=binary")
21
21
  expect(bucket).to be_instance_of(described_class)
22
22
  expect(bucket.name).to eq(bucket_name)
@@ -32,7 +32,7 @@ RSpec.describe BFS::Bucket::S3, s3: true do
32
32
  bucket.close
33
33
  end
34
34
 
35
- it 'should enumerate over a large number of files' do
35
+ it 'enumerates over a large number of files' do
36
36
  bucket = described_class.new bucket_name, prefix: 'm/'
37
37
  expect(bucket.ls('**/*').count).to eq(2121)
38
38
  bucket.close
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bfs-s3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitrij Denissenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-01 00:00:00.000000000 Z
11
+ date: 2021-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-s3
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.8.0
33
+ version: 0.9.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.8.0
40
+ version: 0.9.0
41
41
  description: https://github.com/bsm/bfs.rb
42
42
  email: dimitrij@blacksquaremedia.com
43
43
  executables: []
@@ -67,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  requirements: []
70
- rubygems_version: 3.1.4
70
+ rubygems_version: 3.2.15
71
71
  signing_key:
72
72
  specification_version: 4
73
73
  summary: S3 bucket adapter for bfs