mirror of
https://github.com/octoleo/restic.git
synced 2025-01-02 22:50:19 +00:00
sftp: Only connect once for repository creation
This is especially useful if ssh asks for a password or if closing the initial connection could return an error due to a problematic server implementation.
This commit is contained in:
parent
f7808245aa
commit
cf0a8d7758
11
changelog/unreleased/issue-2152
Normal file
11
changelog/unreleased/issue-2152
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Enhancement: only open connection once for `init` command using sftp backend
|
||||||
|
|
||||||
|
The `init` command using the sftp backend used to connect twice to the
|
||||||
|
repository. This can be inconvenient if the user must enter a password or cause
|
||||||
|
`init` to fail if the server does not correctly close the first sftp
|
||||||
|
connection.
|
||||||
|
|
||||||
|
This has been fixed by reusing the initial sftp connection.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/2152
|
||||||
|
https://github.com/restic/restic/pull/3882
|
@ -44,7 +44,12 @@ var _ restic.Backend = &SFTP{}
|
|||||||
|
|
||||||
const defaultLayout = "default"
|
const defaultLayout = "default"
|
||||||
|
|
||||||
func startClient(program string, args ...string) (*SFTP, error) {
|
func startClient(cfg Config) (*SFTP, error) {
|
||||||
|
program, args, err := buildSSHCommand(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
debug.Log("start client %v %v", program, args)
|
debug.Log("start client %v %v", program, args)
|
||||||
// Connect to a remote host and request the sftp subsystem via the 'ssh'
|
// Connect to a remote host and request the sftp subsystem via the 'ssh'
|
||||||
// command. This assumes that passwordless login is correctly configured.
|
// command. This assumes that passwordless login is correctly configured.
|
||||||
@ -121,22 +126,21 @@ func (r *SFTP) clientError() error {
|
|||||||
func Open(ctx context.Context, cfg Config) (*SFTP, error) {
|
func Open(ctx context.Context, cfg Config) (*SFTP, error) {
|
||||||
debug.Log("open backend with config %#v", cfg)
|
debug.Log("open backend with config %#v", cfg)
|
||||||
|
|
||||||
sem, err := sema.New(cfg.Connections)
|
sftp, err := startClient(cfg)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd, args, err := buildSSHCommand(cfg)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sftp, err := startClient(cmd, args...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("unable to start program: %v", err)
|
debug.Log("unable to start program: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return open(ctx, sftp, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func open(ctx context.Context, sftp *SFTP, cfg Config) (*SFTP, error) {
|
||||||
|
sem, err := sema.New(cfg.Connections)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
sftp.Layout, err = backend.ParseLayout(ctx, sftp, cfg.Layout, defaultLayout, cfg.Path)
|
sftp.Layout, err = backend.ParseLayout(ctx, sftp, cfg.Layout, defaultLayout, cfg.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -230,12 +234,7 @@ func buildSSHCommand(cfg Config) (cmd string, args []string, err error) {
|
|||||||
// Create creates an sftp backend as described by the config by running "ssh"
|
// Create creates an sftp backend as described by the config by running "ssh"
|
||||||
// with the appropriate arguments (or cfg.Command, if set).
|
// with the appropriate arguments (or cfg.Command, if set).
|
||||||
func Create(ctx context.Context, cfg Config) (*SFTP, error) {
|
func Create(ctx context.Context, cfg Config) (*SFTP, error) {
|
||||||
cmd, args, err := buildSSHCommand(cfg)
|
sftp, err := startClient(cfg)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sftp, err := startClient(cmd, args...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("unable to start program: %v", err)
|
debug.Log("unable to start program: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -259,13 +258,8 @@ func Create(ctx context.Context, cfg Config) (*SFTP, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sftp.Close()
|
// repurpose existing connection
|
||||||
if err != nil {
|
return open(ctx, sftp, cfg)
|
||||||
return nil, errors.Wrap(err, "Close")
|
|
||||||
}
|
|
||||||
|
|
||||||
// open backend
|
|
||||||
return Open(ctx, cfg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SFTP) Connections() uint {
|
func (r *SFTP) Connections() uint {
|
||||||
|
Loading…
Reference in New Issue
Block a user