-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial implementation of file transfer utility with configuratio…
…n and database support
- Loading branch information
Showing
9 changed files
with
1,183 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,72 @@ | ||
# CLI_FileTransfer | ||
CLI app written in Go. Acts as an orchestrator and wrapper for multiple utilities. | ||
# CLI File Transfer Utility | ||
|
||
⚠️ **WARNING: This project is in pre-alpha stage and not ready for production use** ⚠️ | ||
|
||
## Description | ||
|
||
A command-line utility for transferring files using various protocols such as Azure Blob Storage, Amazon S3, SFTP, CIFS, and local file transfers. The project aims to provide a simple, unified interface for file transfers across different protocols. | ||
|
||
## Current Status | ||
|
||
This project is under active development and many features are incomplete or not fully tested. | ||
|
||
### Working Features | ||
- Basic TUI (Terminal User Interface) with protocol selection | ||
- Configuration file support | ||
- Local file transfer implementation | ||
- Basic database logging of transfers | ||
- Protocol framework for multiple transfer types | ||
|
||
### In Progress | ||
- SFTP implementation (partial) | ||
- Azure Blob Storage implementation (partial) | ||
- S3 implementation (partial) | ||
- CIFS/SMB implementation (not started) | ||
- Error handling improvements | ||
- Progress reporting | ||
- Transfer validation | ||
- Credential management | ||
- Unit tests | ||
|
||
### Known Issues | ||
- Authentication not fully implemented for remote protocols | ||
- No progress indication during transfers | ||
- Error handling needs improvement | ||
- Configuration validation missing | ||
- No retry mechanism for failed transfers | ||
- Missing proper logging system | ||
- Security considerations need review | ||
|
||
## Supported Protocols (Planned) | ||
|
||
- Azure Blob Storage (`azureblob`) - Partial | ||
- CIFS/SMB (`cifs`) - Not implemented | ||
- SFTP (`sftp`) - Partial | ||
- Amazon S3 (`s3`) - Partial | ||
- Local file system (`local`) - Working | ||
|
||
## Installation | ||
|
||
## Usage | ||
Usage | ||
Interactive Mode (Recommended) | ||
This will start the Terminal User Interface (TUI) where you can: | ||
|
||
Select a transfer protocol using arrow keys | ||
Enter source path | ||
Enter destination path | ||
Command Line Mode | ||
./CLI_FileTransfer -protocol <protocol> -source <source_path> -destination <dest_path> | ||
|
||
# Examples: | ||
# Local file copy | ||
./CLI_FileTransfer -protocol local -source ./myfile.txt -destination ./backup/myfile.txt | ||
|
||
# SFTP transfer | ||
./CLI_FileTransfer -protocol sftp -source ./localfile.txt -destination /remote/path/file.txt | ||
|
||
# S3 upload | ||
./CLI_FileTransfer -protocol s3 -source ./myfile.txt -destination bucket/myfile.txt | ||
|
||
# Azure Blob transfer | ||
./CLI_FileTransfer -protocol azureblob -source ./myfile.txt -destination container/myfile.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/spf13/viper" | ||
"log" | ||
) | ||
|
||
// initConfig initializes the configuration by reading the config file. | ||
func initConfig() { | ||
viper.SetConfigName("config") | ||
viper.SetConfigType("yaml") | ||
viper.AddConfigPath(".") | ||
|
||
// Default configurations | ||
viper.SetDefault("azure.accountName", "") | ||
viper.SetDefault("azure.accountKey", "") | ||
viper.SetDefault("azure.containerName", "") | ||
viper.SetDefault("aws.bucket", "") | ||
viper.SetDefault("aws.region", "") | ||
viper.SetDefault("cifs.mountPoint", "") | ||
viper.SetDefault("sftp.host", "") | ||
viper.SetDefault("sftp.port", "22") | ||
viper.SetDefault("sftp.username", "") | ||
viper.SetDefault("sftp.password", "") | ||
|
||
if err := viper.ReadInConfig(); err != nil { | ||
log.Fatalf("Error reading config file: %v", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
sftp: | ||
username: "your_username" | ||
password: "your_password" | ||
host: "sftp.example.com" | ||
port: 22 | ||
|
||
azureblob: | ||
account_name: "your_account_name" | ||
account_key: "your_account_key" | ||
container_name: "your_container" | ||
|
||
aws: | ||
bucket: "your-bucket-name" | ||
region: "us-west-2" | ||
access_key: "your-access-key" | ||
secret_key: "your-secret-key" | ||
|
||
cifs: | ||
mount_point: "/mnt/share" | ||
username: "domain\\user" | ||
password: "your_password" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package main | ||
|
||
import ( | ||
"database/sql" | ||
_ "github.com/mattn/go-sqlite3" | ||
) | ||
|
||
// initDatabase initializes the SQLite database. | ||
func initDatabase() (*sql.DB, error) { | ||
db, err := sql.Open("sqlite3", "./transfers.db") | ||
if (err != nil) { | ||
return nil, err | ||
} | ||
|
||
sqlStmt := ` | ||
CREATE TABLE IF NOT EXISTS transfers ( | ||
id INTEGER NOT NULL PRIMARY KEY, | ||
protocol TEXT, | ||
source TEXT, | ||
destination TEXT | ||
);` | ||
_, err = db.Exec(sqlStmt) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return db, nil | ||
} | ||
|
||
// logTransfer logs the transfer details into the database. | ||
func logTransfer(db *sql.DB, protocol, source, destination string) error { | ||
stmt, err := db.Prepare("INSERT INTO transfers(protocol, source, destination) values(?,?,?)") | ||
if err != nil { | ||
return err | ||
} | ||
defer stmt.Close() | ||
|
||
_, err = stmt.Exec(protocol, source, destination) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net/url" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/Azure/azure-storage-blob-go/azblob" | ||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/session" | ||
"github.com/aws/aws-sdk-go/service/s3" | ||
"github.com/pkg/sftp" | ||
"github.com/spf13/viper" | ||
"golang.org/x/crypto/ssh" | ||
) | ||
|
||
// transferFile transfers a file using the specified protocol. | ||
// Supported protocols: azureblob, cifs, sftp, s3, local. | ||
func transferFile(protocol, source, destination string) error { | ||
switch protocol { | ||
case "azureblob": | ||
return transferAzureBlob(source, destination) | ||
case "cifs": | ||
return transferCIFS(source, destination) | ||
case "sftp": | ||
return transferSFTP(source, destination) | ||
case "s3": | ||
return transferS3(source, destination) | ||
case "local": | ||
return transferLocal(source, destination) | ||
default: | ||
return fmt.Errorf("unsupported protocol: %s", protocol) | ||
} | ||
} | ||
|
||
// transferAzureBlob uploads a file to Azure Blob Storage. | ||
func transferAzureBlob(source, destination string) error { | ||
log.Println("Transferring via Azure Blob Storage") | ||
|
||
accountName := viper.GetString("azure.accountName") | ||
accountKey := viper.GetString("azure.accountKey") | ||
containerName := viper.GetString("azure.containerName") | ||
|
||
if accountName == "" || accountKey == "" || containerName == "" { | ||
return fmt.Errorf("Azure storage credentials not provided") | ||
} | ||
|
||
credential, err := azblob.NewSharedKeyCredential(accountName, accountKey) | ||
if err != nil { | ||
return fmt.Errorf("failed to create Azure credential: %v", err) | ||
} | ||
|
||
pipeline := azblob.NewPipeline(credential, azblob.PipelineOptions{}) | ||
url, _ := url.Parse( | ||
fmt.Sprintf("https://%s.blob.core.windows.net/%s", accountName, containerName)) | ||
|
||
containerURL := azblob.NewContainerURL(*url, pipeline) | ||
blobURL := containerURL.NewBlockBlobURL(filepath.Base(destination)) | ||
|
||
file, err := os.Open(source) | ||
if err != nil { | ||
return fmt.Errorf("failed to open source file: %v", err) | ||
} | ||
defer file.Close() | ||
|
||
ctx := context.Background() | ||
_, err = azblob.UploadFileToBlockBlob(ctx, file, blobURL, azblob.UploadToBlockBlobOptions{}) | ||
if err != nil { | ||
return fmt.Errorf("failed to upload file to Azure Blob: %v", err) | ||
} | ||
|
||
log.Println("File transferred via Azure Blob Storage successfully") | ||
return nil | ||
} | ||
|
||
// transferCIFS copies a file to a CIFS (SMB) network share. | ||
func transferCIFS(source, destination string) error { | ||
log.Println("Transferring via CIFS") | ||
|
||
mountPoint := viper.GetString("cifs.mountPoint") | ||
if mountPoint == "" { | ||
return fmt.Errorf("CIFS mount point not configured") | ||
} | ||
|
||
destPath := filepath.Join(mountPoint, destination) | ||
return transferLocal(source, destPath) | ||
} | ||
|
||
// transferSFTP uploads a file via SFTP. | ||
func transferSFTP(source, destination string) error { | ||
// SSH client configuration | ||
config := &ssh.ClientConfig{ | ||
User: "username", | ||
Auth: []ssh.AuthMethod{ | ||
ssh.Password("password"), | ||
}, | ||
HostKeyCallback: ssh.InsecureIgnoreHostKey(), | ||
} | ||
|
||
// Connect to the SSH server | ||
sshClient, err := ssh.Dial("tcp", "sftp.example.com:22", config) | ||
if (err != nil) { | ||
return fmt.Errorf("failed to dial: %v", err) | ||
} | ||
defer sshClient.Close() | ||
|
||
// Create new SFTP client | ||
sftpClient, err := sftp.NewClient(sshClient) | ||
if (err != nil) { | ||
return fmt.Errorf("failed to create sftp client: %v", err) | ||
} | ||
defer sftpClient.Close() | ||
|
||
// Open source file | ||
srcFile, err := os.Open(source) | ||
if (err != nil) { | ||
return fmt.Errorf("failed to open source file: %v", err) | ||
} | ||
defer srcFile.Close() | ||
|
||
// Create destination file on the server | ||
dstFile, err := sftpClient.Create(destination) | ||
if (err != nil) { | ||
return fmt.Errorf("failed to create destination file: %v", err) | ||
} | ||
defer dstFile.Close() | ||
|
||
// Copy data from source file to destination file | ||
_, err = io.Copy(dstFile, srcFile) | ||
if (err != nil) { | ||
return fmt.Errorf("failed to copy file: %v", err) | ||
} | ||
|
||
log.Println("File transferred via SFTP successfully") | ||
return nil | ||
} | ||
|
||
// transferS3 uploads a file to Amazon S3. | ||
func transferS3(source, destination string) error { | ||
log.Println("Transferring via Amazon S3") | ||
|
||
bucket := viper.GetString("aws.bucket") | ||
region := viper.GetString("aws.region") | ||
|
||
if bucket == "" || region == "" { | ||
return fmt.Errorf("AWS S3 bucket or region not configured") | ||
} | ||
|
||
sess, err := session.NewSession(&aws.Config{Region: aws.String(region)}) | ||
if err != nil { | ||
return fmt.Errorf("failed to create AWS session: %v", err) | ||
} | ||
|
||
uploader := s3.New(sess) | ||
file, err := os.Open(source) | ||
if err != nil { | ||
return fmt.Errorf("failed to open source file: %v", err) | ||
} | ||
defer file.Close() | ||
|
||
_, err = uploader.PutObject(&s3.PutObjectInput{ | ||
Bucket: aws.String(bucket), | ||
Key: aws.String(destination), | ||
Body: file, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed to upload to S3: %v", err) | ||
} | ||
|
||
log.Println("File transferred via Amazon S3 successfully") | ||
return nil | ||
} | ||
|
||
// transferLocal copies a file locally. | ||
func transferLocal(source, destination string) error { | ||
// Copying file from source to destination locally | ||
inputFile, err := os.Open(source) | ||
if err != nil { | ||
return fmt.Errorf("failed to open source file: %v", err) | ||
} | ||
defer inputFile.Close() | ||
|
||
outputFile, err := os.Create(destination) | ||
if err != nil { | ||
return fmt.Errorf("failed to create destination file: %v", err) | ||
} | ||
defer outputFile.Close() | ||
|
||
_, err = io.Copy(outputFile, inputFile) | ||
if err != nil { | ||
return fmt.Errorf("failed to copy file: %v", err) | ||
} | ||
|
||
log.Println("File transferred locally successfully") | ||
return nil | ||
} |
Oops, something went wrong.