github.com/fawick/restic@v0.1.1-0.20171126184616-c02923fbfc79/internal/backend/s3/config.go (about) 1 package s3 2 3 import ( 4 "net/url" 5 "path" 6 "strings" 7 8 "github.com/restic/restic/internal/errors" 9 "github.com/restic/restic/internal/options" 10 ) 11 12 // Config contains all configuration necessary to connect to an s3 compatible 13 // server. 14 type Config struct { 15 Endpoint string 16 UseHTTP bool 17 KeyID, Secret string 18 Bucket string 19 Prefix string 20 Layout string `option:"layout" help:"use this backend layout (default: auto-detect)"` 21 22 Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 5)"` 23 MaxRetries uint `option:"retries" help:"set the number of retries attempted"` 24 } 25 26 // NewConfig returns a new Config with the default values filled in. 27 func NewConfig() Config { 28 return Config{ 29 Connections: 5, 30 } 31 } 32 33 func init() { 34 options.Register("s3", Config{}) 35 } 36 37 // ParseConfig parses the string s and extracts the s3 config. The two 38 // supported configuration formats are s3://host/bucketname/prefix and 39 // s3:host/bucketname/prefix. The host can also be a valid s3 region 40 // name. If no prefix is given the prefix "restic" will be used. 41 func ParseConfig(s string) (interface{}, error) { 42 switch { 43 case strings.HasPrefix(s, "s3:http"): 44 // assume that a URL has been specified, parse it and 45 // use the host as the endpoint and the path as the 46 // bucket name and prefix 47 url, err := url.Parse(s[3:]) 48 if err != nil { 49 return nil, errors.Wrap(err, "url.Parse") 50 } 51 52 if url.Path == "" { 53 return nil, errors.New("s3: bucket name not found") 54 } 55 56 path := strings.SplitN(url.Path[1:], "/", 2) 57 return createConfig(url.Host, path, url.Scheme == "http") 58 case strings.HasPrefix(s, "s3://"): 59 s = s[5:] 60 case strings.HasPrefix(s, "s3:"): 61 s = s[3:] 62 default: 63 return nil, errors.New("s3: invalid format") 64 } 65 // use the first entry of the path as the endpoint and the 66 // remainder as bucket name and prefix 67 path := strings.SplitN(s, "/", 3) 68 return createConfig(path[0], path[1:], false) 69 } 70 71 func createConfig(endpoint string, p []string, useHTTP bool) (interface{}, error) { 72 if len(p) < 1 { 73 return nil, errors.New("s3: invalid format, host/region or bucket name not found") 74 } 75 76 var prefix string 77 if len(p) > 1 && p[1] != "" { 78 prefix = path.Clean(p[1]) 79 } 80 81 cfg := NewConfig() 82 cfg.Endpoint = endpoint 83 cfg.UseHTTP = useHTTP 84 cfg.Bucket = p[0] 85 cfg.Prefix = prefix 86 return cfg, nil 87 }