restic/internal/backend/s3/config.go

90 lines
2.4 KiB
Go
Raw Normal View History

2015-12-28 14:51:24 +00:00
package s3
import (
2015-12-28 17:23:02 +00:00
"net/url"
"path"
2015-12-28 14:51:24 +00:00
"strings"
2017-07-23 12:21:03 +00:00
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/options"
2015-12-28 14:51:24 +00:00
)
// Config contains all configuration necessary to connect to an s3 compatible
// server.
type Config struct {
2015-12-28 23:27:29 +00:00
Endpoint string
UseHTTP bool
2015-12-28 14:51:24 +00:00
KeyID, Secret string
Bucket string
Prefix string
Layout string `option:"layout" help:"use this backend layout (default: auto-detect)"`
2017-06-05 22:17:39 +00:00
Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 5)"`
MaxRetries uint `option:"retries" help:"set the number of retries attempted"`
2017-06-05 22:17:39 +00:00
}
// NewConfig returns a new Config with the default values filled in.
func NewConfig() Config {
return Config{
Connections: 5,
2017-06-05 22:17:39 +00:00
}
}
func init() {
options.Register("s3", Config{})
2015-12-28 14:51:24 +00:00
}
const defaultPrefix = "restic"
2015-12-28 14:51:24 +00:00
// ParseConfig parses the string s and extracts the s3 config. The two
// supported configuration formats are s3://host/bucketname/prefix and
2017-11-20 21:21:39 +00:00
// s3:host/bucketname/prefix. The host can also be a valid s3 region
// name. If no prefix is given the prefix "restic" will be used.
2015-12-28 14:51:24 +00:00
func ParseConfig(s string) (interface{}, error) {
2016-02-14 15:01:14 +00:00
switch {
case strings.HasPrefix(s, "s3:http"):
// assume that a URL has been specified, parse it and
// use the host as the endpoint and the path as the
// bucket name and prefix
url, err := url.Parse(s[3:])
2015-12-28 17:23:02 +00:00
if err != nil {
2016-08-29 19:54:50 +00:00
return nil, errors.Wrap(err, "url.Parse")
2015-12-28 17:23:02 +00:00
}
if url.Path == "" {
return nil, errors.New("s3: bucket name not found")
}
path := strings.SplitN(url.Path[1:], "/", 2)
return createConfig(url.Host, path, url.Scheme == "http")
case strings.HasPrefix(s, "s3://"):
s = s[5:]
2016-02-14 15:01:14 +00:00
case strings.HasPrefix(s, "s3:"):
s = s[3:]
2016-02-14 15:01:14 +00:00
default:
return nil, errors.New("s3: invalid format")
}
// use the first entry of the path as the endpoint and the
// remainder as bucket name and prefix
path := strings.SplitN(s, "/", 3)
return createConfig(path[0], path[1:], false)
}
func createConfig(endpoint string, p []string, useHTTP bool) (interface{}, error) {
var prefix string
switch {
case len(p) < 1:
return nil, errors.New("s3: invalid format, host/region or bucket name not found")
case len(p) == 1 || p[1] == "":
prefix = defaultPrefix
default:
prefix = path.Clean(p[1])
}
2017-06-05 22:17:39 +00:00
cfg := NewConfig()
cfg.Endpoint = endpoint
cfg.UseHTTP = useHTTP
cfg.Bucket = p[0]
cfg.Prefix = prefix
return cfg, nil
2015-12-28 14:51:24 +00:00
}