class Eco::API::UseCases::DefaultCases::Samples::Sftp < Eco::API::Common::Loaders::UseCase name "sftp-sample" type :other CONST_REFERRAL = /^(?:::)?(?:[A-Z][a-zA-Z0-9_]*(?:::[A-Z][a-zA-Z0-9_]*)*)$/ def main(session, options, usecase) options[:end_get] = false raise "The SFTP is not configured" unless session.sftp? case options.dig(:sftp, :command) when :list list_folder when :get get_files when :get_last get_last when :archive archive_files end end private # Can't pass this via CLI option, as it breaks the regular expression def file_pattern fpc = file_pattern_const return fpc if fpc raise "You should redefine the file_pattern function as a RegEx expression that matches the target remote file" end def file_pattern_const if fpc = options.dig(:sftp, :file_pattern_const) raise "Invalid file pattern const referral: #{fpc}" unless fpc.match(CONST_REFERRAL) self.eval(fpc) end end # Ex: "/IN/Personnel" def remote_subfolder rm_sf = options.dig(:sftp, :remote_subfolder) return rm_sf if rm_sf raise "You should redefine remote_subfolder as the folder where the target file sits. Ex: /IN/Personnel" end # `remote_target_folder` overrides `sftp_config.remote_folder` as well as `remote_subfolder` # `remote_folder` overrides `sftp_config.remote_folder` but NOT `remote_subfolder` def remote_folder rm_tf = options.dig(:sftp, :remote_target_folder) rm_fd = options.dig(:sftp, :remote_folder) || sftp_config.remote_folder rm_tf || File.join(rm_fd, remote_subfolder) end def to_remote_path(file) File.join(remote_folder, file) end def local_folder options.dig(:sftp, :local_folder) || "." end def with_remote_files begin sftp.files(remote_folder, pattern: file_pattern).each do |remote_file| yield(remote_file) if block_given? end rescue Net::SFTP::StatusException => e logger.error("SFTP samplecase: There was an error trying to access the remote folder '#{remote_folder}'") [] end end def list_folder puts "Listing remote folder: '#{remote_folder}' (host: #{sftp.host}):" with_remote_files {|file| puts file.longname} end def get_files with_remote_files.tap do |files| unless files.empty? file_names = files.map {|file| to_remote_path(file.name)} puts "Getting the following files into the local folder '#{local_folder}':" puts file_names sftp.download(file_names, local_folder: local_folder) end end end def get_last with_remote_files.last.tap do |file| if file file_name = to_remote_path(file.name) puts "Getting the following file: #{file_name}" sftp.download(file_name, local_folder: local_folder) end end end def archive_files with_remote_files do |file| source = to_remote_path(file.name) # should probably be file.longname dest = to_remote_path("#{archive_subfolder}/#{file.name}") move_file(source, dest) end.tap do |files| puts "Moved the file(s) to the #{archive_subfolder} folder" unless files.empty? end end def move_file(source, dest) sftp.move(source, dest, 0x0001) do |response| if response.ok? puts "#{source}\n -to-> #{dest}" else puts "Could not move file #{source}" end end end def archive_subfolder "Archive" end def sftp_config session.config.sftp end def sftp session.sftp end end