class BFS::Bucket::SFTP

SFTP buckets are operating on SFTP connections.

Constants

StatusCodes

Public Class Methods

new(host, prefix: nil, **opts) click to toggle source

Initializes a new bucket @param [String] host the host name @param [Hash] opts options @option opts [Integer] :port custom port. Default: 22. @option opts [String] :user user name for login. @option opts [String] :password password for login. @option opts [String] :prefix optional prefix. @option opts [Boolean] :compression use compression. @option opts [Boolean] :keepalive use keepalive. @option opts [Integer] :keepalive_interval interval if keepalive enabled. Default: 300. @option opts [Array<String>] :keys an array of file names of private keys to use for publickey and hostbased authentication. @option opts [Boolean|Symbol] :verify_host_key specifying how strict host-key verification should be, either false, true, :very, or :secure.

Calls superclass method
# File lib/bfs/bucket/sftp.rb, line 22
def initialize(host, prefix: nil, **opts)
  super(**opts)

  @prefix  = prefix
  @session = Net::SSH.start(host, nil, **opts.slice(*Net::SSH::VALID_OPTIONS), non_interactive: true)

  if @prefix # rubocop:disable Style/GuardClause
    @prefix = "#{norm_path(@prefix)}/"
    mkdir_p @prefix
  end
end

Public Instance Methods

close() click to toggle source

Closes the underlying connection

# File lib/bfs/bucket/sftp.rb, line 100
def close
  @session.close unless @session.closed?
end
create(path, encoding: self.encoding, perm: self.perm, **opts, &block) click to toggle source

Creates a new file and opens it for writing @option opts [String|Encoding] :encoding Custom file encoding. @option opts [Integer] :perm Custom file permission, default: 0600.

# File lib/bfs/bucket/sftp.rb, line 67
def create(path, encoding: self.encoding, perm: self.perm, **opts, &block)
  full = full_path(path)

  opts[:preserve] = true if perm && !opts.key?(:preserve)
  BFS::Writer.new(path, encoding: encoding, perm: perm) do |temp_path|
    mkdir_p File.dirname(full)
    @session.sftp.upload!(temp_path, full, **opts)
  end.perform(&block)
end
glob(pattern = '**/*', **_opts) click to toggle source

Iterates over the contents of a bucket using a glob pattern

# File lib/bfs/bucket/sftp.rb, line 42
def glob(pattern = '**/*', **_opts)
  Enumerator.new do |acc|
    walk(pattern) do |path, attrs|
      acc << file_info(path, attrs)
    end
  end
end
info(path, **_opts) click to toggle source

Info returns the object info

# File lib/bfs/bucket/sftp.rb, line 51
def info(path, **_opts)
  full = full_path(path)
  path = norm_path(path)
  attrs = @session.sftp.stat!(full)
  raise BFS::FileNotFound, path unless attrs.file?

  file_info path, attrs
rescue Net::SFTP::StatusException => e
  raise BFS::FileNotFound, path if e.code == StatusCodes::FX_NO_SUCH_FILE

  raise
end
ls(pattern = '**/*', **_opts) click to toggle source

Lists the contents of a bucket using a glob pattern

# File lib/bfs/bucket/sftp.rb, line 35
def ls(pattern = '**/*', **_opts)
  Enumerator.new do |acc|
    walk(pattern) {|path, _| acc << path }
  end
end
open(path, encoding: self.encoding, tempdir: nil, **_opts, &block) click to toggle source

Opens an existing file for reading

# File lib/bfs/bucket/sftp.rb, line 78
def open(path, encoding: self.encoding, tempdir: nil, **_opts, &block)
  full = full_path(path)
  temp = Tempfile.new(File.basename(path), tempdir, encoding: encoding)
  temp.close

  @session.sftp.download!(full, temp.path)
  File.open(temp.path, encoding: encoding, &block)
rescue Net::SFTP::StatusException => e
  raise BFS::FileNotFound, path if e.code == StatusCodes::FX_NO_SUCH_FILE

  raise
end
rm(path, **_opts) click to toggle source

Deletes a file.

# File lib/bfs/bucket/sftp.rb, line 92
def rm(path, **_opts)
  full = full_path(path)
  @session.sftp.remove!(full)
rescue Net::SFTP::StatusException => e
  raise unless e.code == StatusCodes::FX_NO_SUCH_FILE
end

Private Instance Methods

file_info(path, attrs) click to toggle source
# File lib/bfs/bucket/sftp.rb, line 106
def file_info(path, attrs)
  BFS::FileInfo.new(path: path, size: attrs.size.to_i, mtime: Time.at(attrs.mtime.to_i), mode: BFS.norm_mode(attrs.permissions))
end
mkdir_p(path) click to toggle source
# File lib/bfs/bucket/sftp.rb, line 119
def mkdir_p(path)
  parts = path.split('/').reject(&:empty?)
  cmds  = (0...parts.size).map do |i|
    @session.sftp.mkdir parts[0..i].join('/')
  end
  cmds.each do |req|
    req.wait
    next if req.response.code <= StatusCodes::FX_FAILURE

    raise Net::SFTP::StatusException, req.response
  end
end
walk(pattern) { |path, attributes| ... } click to toggle source
# File lib/bfs/bucket/sftp.rb, line 110
def walk(pattern)
  @session.sftp.dir.glob(@prefix || '/', pattern) do |ent|
    next unless ent.file?

    path = norm_path(ent.name)
    yield(path, ent.attributes)
  end
end