class BFS::Bucket::S3
S3
buckets are operating on s3
Attributes
Public Class Methods
Initializes a new S3
bucket @param [String] name the bucket name @param [Hash] opts options @option opts [String] :region default region @option opts [String] :prefix custom namespace within the bucket @option opts [String] :sse default server-side-encryption setting @option opts [Aws::Credentials] :credentials credentials object @option opts [String] :access_key_id custom AWS access key ID @option opts [String] :secret_access_key custom AWS secret access key @option opts [String] :profile_name custom AWS profile name (for shared credentials) @option opts [Symbol] :acl canned ACL @option opts [String] :storage_class storage class @option opts [Aws::S3::Client] :client custom client, uses default_client by default
# File lib/bfs/bucket/s3.rb, line 23 def initialize(name, **opts) super(**opts) @name = name @sse = opts[:sse] || opts[:server_side_encryption] @prefix = opts[:prefix] @acl = opts[:acl].to_sym if opts[:acl] @storage_class = opts[:storage_class] @client = opts[:client] || init_client(**opts) end
Public Instance Methods
Copies a file.
# File lib/bfs/bucket/s3.rb, line 123 def cp(src, dst, **opts) src = full_path(src) dst = full_path(dst) opts = opts.merge( bucket: name, copy_source: "/#{name}/#{src}", key: dst, ) @client.copy_object(**opts) rescue Aws::S3::Errors::NoSuchKey, Aws::S3::Errors::NoSuchBucket, Aws::S3::Errors::NotFound raise BFS::FileNotFound, trim_prefix(src) end
Creates a new file and opens it for writing @param [String] path @param [Hash] opts options @option opts [String] :encoding Custom encoding. @option opts [String] :acl custom ACL override @option opts [String] :server_side_encryption SSE override @option opts [String] :storage_class storage class override
# File lib/bfs/bucket/s3.rb, line 72 def create(path, encoding: self.encoding, perm: self.perm, **opts, &block) path = full_path(path) opts = opts.merge( bucket: name, key: path, ) opts[:acl] ||= @acl if @acl opts[:server_side_encryption] ||= @sse if @sse opts[:storage_class] ||= @storage_class if @storage_class BFS::Writer.new(path, encoding: encoding, perm: perm) do |t| File.open(t, encoding: encoding) do |file| @client.put_object(opts.merge(body: file)) end end.perform(&block) end
Iterates over the contents of a bucket using a glob pattern
# File lib/bfs/bucket/s3.rb, line 44 def glob(pattern = '**/*', **opts) Enumerator.new do |acc| walk(pattern, **opts) do |path, obj| info = BFS::FileInfo.new(path: path, size: obj.size, mtime: obj.last_modified) acc << info end end end
Info returns the object info
# File lib/bfs/bucket/s3.rb, line 54 def info(path, **opts) path = norm_path(path) opts = opts.merge(bucket: name, key: full_path(path)) info = @client.head_object(**opts) raise BFS::FileNotFound, path unless info BFS::FileInfo.new path: path, size: info.content_length, mtime: info.last_modified, content_type: info.content_type, metadata: norm_meta(info.metadata) rescue Aws::S3::Errors::NoSuchKey, Aws::S3::Errors::NoSuchBucket, Aws::S3::Errors::NotFound raise BFS::FileNotFound, path end
Lists the contents of a bucket using a glob pattern
# File lib/bfs/bucket/s3.rb, line 35 def ls(pattern = '**/*', **opts) Enumerator.new do |acc| walk(pattern, **opts) do |path, _| acc << path end end end
Opens an existing file for reading @param [String] path @param [Hash] opts options @option opts [String] :encoding Custom encoding. @option opts [String] :tempdir Custom temp dir.
# File lib/bfs/bucket/s3.rb, line 94 def open(path, encoding: self.encoding, tempdir: nil, **opts, &block) path = full_path(path) temp = Tempfile.new(File.basename(path), tempdir, encoding: encoding) temp.close opts = opts.merge( response_target: temp.path, bucket: name, key: path, ) @client.get_object(**opts) File.open(temp.path, encoding: encoding, &block) rescue Aws::S3::Errors::NoSuchKey, Aws::S3::Errors::NoSuchBucket, Aws::S3::Errors::NotFound raise BFS::FileNotFound, trim_prefix(path) end
Deletes a file.
# File lib/bfs/bucket/s3.rb, line 112 def rm(path, **opts) path = full_path(path) opts = opts.merge( bucket: name, key: path, ) @client.delete_object(**opts) rescue Aws::S3::Errors::NoSuchKey, Aws::S3::Errors::NoSuchBucket, Aws::S3::Errors::NotFound # rubocop:disable Lint/SuppressedException end
Private Instance Methods
# File lib/bfs/bucket/s3.rb, line 149 def assume_role_credentials(role_arn, credentials = nil) opts = { role_arn: role_arn, role_session_name: SecureRandom.urlsafe_base64(12), } opts[:client] = Aws::STS::Client.new(credentials: credentials) if credentials Aws::AssumeRoleCredentials.new(**opts) end
# File lib/bfs/bucket/s3.rb, line 138 def init_client(**opts) config = {} config[:region] = opts[:region] if opts[:region] config[:credentials] = opts[:credentials] if opts[:credentials] config[:credentials] ||= Aws::Credentials.new(opts[:access_key_id].to_s, opts[:secret_access_key].to_s) if opts[:access_key_id] config[:credentials] ||= Aws::SharedCredentials.new(profile_name: opts[:profile_name]) if opts[:profile_name] config[:credentials] = assume_role_credentials(opts[:assume_role], config[:credentials]) if opts[:assume_role] Aws::S3::Client.new(config) end
# File lib/bfs/bucket/s3.rb, line 158 def walk(pattern, **opts) prefix = pattern[%r{^[^*?\{\}\[\]]+/}] prefix = File.join(*[@prefix, prefix].compact) if @prefix opts = opts.merge(bucket: name, prefix: @prefix) opts[:prefix] = prefix if prefix next_token = nil loop do resp = @client.list_objects_v2 opts.merge(continuation_token: next_token) resp.contents.each do |obj| path = trim_prefix(obj.key) yield(path, obj) if File.fnmatch?(pattern, path, File::FNM_PATHNAME) end next_token = resp.next_continuation_token.to_s break if next_token.empty? end end