publish-vod/pkg/uploader/sftp/sftp.go

84 lines
2 KiB
Go
Raw Normal View History

package sftp
import (
"context"
"fmt"
"net"
"os"
"path"
"git.luzifer.io/luzifer/publish-vod/pkg/uploader"
"github.com/Luzifer/go_helpers/v2/fieldcollection"
pkgSFTP "github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
)
type (
Uploader struct{}
)
var (
ptrStringEmpty = func(v string) *string { return &v }("")
_ uploader.Uploader = Uploader{}
)
func (Uploader) Prepare(context.Context, uploader.UploaderOpts) error { return nil }
func (Uploader) UploadFile(ctx context.Context, opts uploader.UploaderOpts) error {
socket := os.Getenv("SSH_AUTH_SOCK")
conn, err := net.Dial("unix", socket)
if err != nil {
return fmt.Errorf("opening SSH_AUTH_SOCK: %w", err)
}
agentClient := agent.NewClient(conn)
config := &ssh.ClientConfig{
User: opts.Config.MustString("user", nil),
Auth: []ssh.AuthMethod{
// Use a callback rather than PublicKeys so we only consult the
// agent once the remote server wants it.
ssh.PublicKeysCallback(agentClient.Signers),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
client, err := ssh.Dial("tcp", opts.Config.MustString("host", nil), config)
if err != nil {
return fmt.Errorf("dialing SSH server: %w", err)
}
defer client.Close()
sftpClient, err := pkgSFTP.NewClient(client)
if err != nil {
return fmt.Errorf("creating sftp client: %w", err)
}
defer sftpClient.Close()
remoteFile := path.Join(opts.Config.MustString("path", nil), path.Base(opts.Filename))
f, err := sftpClient.OpenFile(remoteFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
if err != nil {
return fmt.Errorf("opening remote file: %w", err)
}
defer f.Close()
progressReader := opts.ProgressBar.NewProxyReader(opts.Content)
f.ReadFrom(progressReader)
opts.FinalMessage("Video uploaded to %s", remoteFile)
return nil
}
func (Uploader) ValidateConfig(config *fieldcollection.FieldCollection) error {
for _, key := range []string{"host", "path", "user"} {
if v, err := config.String(key); err != nil || v == "" {
return fmt.Errorf("key %q must be non-empty string", key)
}
}
return nil
}