github.com/rudderlabs/rudder-go-kit@v0.30.0/sftp/sftp.go (about)

     1  package sftp
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"golang.org/x/crypto/ssh"
    10  )
    11  
    12  const (
    13  	// PasswordAuth indicates password-based authentication
    14  	PasswordAuth = "passwordAuth"
    15  	// KeyAuth indicates key-based authentication
    16  	KeyAuth = "keyAuth"
    17  )
    18  
    19  // FileManager is an interface for managing files on a remote server
    20  type FileManager interface {
    21  	Upload(localFilePath, remoteDir string) error
    22  	Download(remoteFilePath, localDir string) error
    23  	Delete(remoteFilePath string) error
    24  }
    25  
    26  // fileManagerImpl is a real implementation of FileManager
    27  type fileManagerImpl struct {
    28  	client Client
    29  }
    30  
    31  func NewFileManager(sshClient *ssh.Client) (FileManager, error) {
    32  	sftpClient, err := newSFTPClient(sshClient)
    33  	if err != nil {
    34  		return nil, fmt.Errorf("cannot create SFTP client: %w", err)
    35  	}
    36  	return &fileManagerImpl{client: sftpClient}, nil
    37  }
    38  
    39  // Upload uploads a file to the remote server
    40  func (fm *fileManagerImpl) Upload(localFilePath, remoteFilePath string) error {
    41  	localFile, err := os.Open(localFilePath)
    42  	if err != nil {
    43  		return fmt.Errorf("cannot open local file: %w", err)
    44  	}
    45  	defer func() {
    46  		_ = localFile.Close()
    47  	}()
    48  
    49  	// Create the directory if it does not exist
    50  	remoteDir := filepath.Dir(remoteFilePath)
    51  	if err := fm.client.MkdirAll(remoteDir); err != nil {
    52  		return fmt.Errorf("cannot create remote directory: %w", err)
    53  	}
    54  
    55  	remoteFile, err := fm.client.OpenFile(remoteFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
    56  	if err != nil {
    57  		return fmt.Errorf("cannot create remote file: %w", err)
    58  	}
    59  	defer func() {
    60  		_ = remoteFile.Close()
    61  	}()
    62  
    63  	_, err = io.Copy(remoteFile, localFile)
    64  	if err != nil {
    65  		return fmt.Errorf("error copying file: %w", err)
    66  	}
    67  
    68  	return nil
    69  }
    70  
    71  // Download downloads a file from the remote server
    72  func (fm *fileManagerImpl) Download(remoteFilePath, localDir string) error {
    73  	remoteFile, err := fm.client.OpenFile(remoteFilePath, os.O_RDONLY)
    74  	if err != nil {
    75  		return fmt.Errorf("cannot open remote file: %w", err)
    76  	}
    77  	defer func() {
    78  		_ = remoteFile.Close()
    79  	}()
    80  
    81  	localFileName := filepath.Join(localDir, filepath.Base(remoteFilePath))
    82  	localFile, err := os.Create(localFileName)
    83  	if err != nil {
    84  		return fmt.Errorf("cannot create local file: %w", err)
    85  	}
    86  	defer func() {
    87  		_ = localFile.Close()
    88  	}()
    89  
    90  	_, err = io.Copy(localFile, remoteFile)
    91  	if err != nil {
    92  		return fmt.Errorf("cannot copy remote file content to local file: %w", err)
    93  	}
    94  
    95  	return nil
    96  }
    97  
    98  // Delete deletes a file on the remote server
    99  func (fm *fileManagerImpl) Delete(remoteFilePath string) error {
   100  	err := fm.client.Remove(remoteFilePath)
   101  	if err != nil {
   102  		return fmt.Errorf("cannot delete file: %w", err)
   103  	}
   104  
   105  	return nil
   106  }