2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-22 12:55:18 +00:00

backend: add standardized Config.ApplyEnvironment

This removes the backend specific special cases while parsing the
configuration in `global.go`.
This commit is contained in:
Michael Eischer 2023-04-21 21:51:58 +02:00
parent f903db492c
commit 32a6b66267
8 changed files with 68 additions and 144 deletions

View File

@ -535,112 +535,21 @@ func OpenRepository(ctx context.Context, opts GlobalOptions) (*repository.Reposi
} }
func parseConfig(loc location.Location, opts options.Options) (interface{}, error) { func parseConfig(loc location.Location, opts options.Options) (interface{}, error) {
// only apply options for a particular backend here cfg := loc.Config
opts = opts.Extract(loc.Scheme) if cfg, ok := cfg.(restic.ApplyEnvironmenter); ok {
if err := cfg.ApplyEnvironment(""); err != nil {
switch loc.Scheme {
case "local":
cfg := loc.Config.(*local.Config)
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err return nil, err
} }
debug.Log("opening local repository at %#v", cfg)
return cfg, nil
case "sftp":
cfg := loc.Config.(*sftp.Config)
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening sftp repository at %#v", cfg)
return cfg, nil
case "s3":
cfg := loc.Config.(*s3.Config)
if err := s3.ApplyEnvironment(cfg); err != nil {
return nil, err
}
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening s3 repository at %#v", cfg)
return cfg, nil
case "gs":
cfg := loc.Config.(*gs.Config)
if err := gs.ApplyEnvironment(cfg); err != nil {
return nil, err
}
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening gs repository at %#v", cfg)
return cfg, nil
case "azure":
cfg := loc.Config.(*azure.Config)
if err := azure.ApplyEnvironment(cfg); err != nil {
return nil, err
}
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening gs repository at %#v", cfg)
return cfg, nil
case "swift":
cfg := loc.Config.(*swift.Config)
if err := swift.ApplyEnvironment("", cfg); err != nil {
return nil, err
}
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening swift repository at %#v", cfg)
return cfg, nil
case "b2":
cfg := loc.Config.(*b2.Config)
if err := b2.ApplyEnvironment(cfg); err != nil {
return nil, err
}
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening b2 repository at %#v", cfg)
return cfg, nil
case "rest":
cfg := loc.Config.(*rest.Config)
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening rest repository at %#v", cfg)
return cfg, nil
case "rclone":
cfg := loc.Config.(*rclone.Config)
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening rest repository at %#v", cfg)
return cfg, nil
} }
return nil, errors.Fatalf("invalid backend: %q", loc.Scheme) // only apply options for a particular backend here
opts = opts.Extract(loc.Scheme)
if err := opts.Apply(loc.Scheme, cfg); err != nil {
return nil, err
}
debug.Log("opening %v repository at %#v", loc.Scheme, cfg)
return cfg, nil
} }
// Open the backend specified by a location config. // Open the backend specified by a location config.

View File

@ -7,6 +7,7 @@ import (
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/options" "github.com/restic/restic/internal/options"
"github.com/restic/restic/internal/restic"
) )
// Config contains all configuration necessary to connect to an azure compatible // Config contains all configuration necessary to connect to an azure compatible
@ -55,19 +56,20 @@ func ParseConfig(s string) (*Config, error) {
return &cfg, nil return &cfg, nil
} }
var _ restic.ApplyEnvironmenter = &Config{}
// ApplyEnvironment saves values from the environment to the config. // ApplyEnvironment saves values from the environment to the config.
func ApplyEnvironment(cfgRaw interface{}) error { func (cfg *Config) ApplyEnvironment(prefix string) error {
cfg := cfgRaw.(*Config)
if cfg.AccountName == "" { if cfg.AccountName == "" {
cfg.AccountName = os.Getenv("AZURE_ACCOUNT_NAME") cfg.AccountName = os.Getenv(prefix + "AZURE_ACCOUNT_NAME")
} }
if cfg.AccountKey.String() == "" { if cfg.AccountKey.String() == "" {
cfg.AccountKey = options.NewSecretString(os.Getenv("AZURE_ACCOUNT_KEY")) cfg.AccountKey = options.NewSecretString(os.Getenv(prefix + "AZURE_ACCOUNT_KEY"))
} }
if cfg.AccountSAS.String() == "" { if cfg.AccountSAS.String() == "" {
cfg.AccountSAS = options.NewSecretString(os.Getenv("AZURE_ACCOUNT_SAS")) cfg.AccountSAS = options.NewSecretString(os.Getenv(prefix + "AZURE_ACCOUNT_SAS"))
} }
return nil return nil
} }

View File

@ -8,6 +8,7 @@ import (
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/options" "github.com/restic/restic/internal/options"
"github.com/restic/restic/internal/restic"
) )
// Config contains all configuration necessary to connect to an b2 compatible // Config contains all configuration necessary to connect to an b2 compatible
@ -81,11 +82,12 @@ func ParseConfig(s string) (*Config, error) {
return &cfg, nil return &cfg, nil
} }
var _ restic.ApplyEnvironmenter = &Config{}
// ApplyEnvironment saves values from the environment to the config. // ApplyEnvironment saves values from the environment to the config.
func ApplyEnvironment(cfgRaw interface{}) error { func (cfg *Config) ApplyEnvironment(prefix string) error {
cfg := cfgRaw.(*Config)
if cfg.AccountID == "" { if cfg.AccountID == "" {
cfg.AccountID = os.Getenv("B2_ACCOUNT_ID") cfg.AccountID = os.Getenv(prefix + "B2_ACCOUNT_ID")
} }
if cfg.AccountID == "" { if cfg.AccountID == "" {
@ -93,7 +95,7 @@ func ApplyEnvironment(cfgRaw interface{}) error {
} }
if cfg.Key.String() == "" { if cfg.Key.String() == "" {
cfg.Key = options.NewSecretString(os.Getenv("B2_ACCOUNT_KEY")) cfg.Key = options.NewSecretString(os.Getenv(prefix + "B2_ACCOUNT_KEY"))
} }
if cfg.Key.String() == "" { if cfg.Key.String() == "" {

View File

@ -7,6 +7,7 @@ import (
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/options" "github.com/restic/restic/internal/options"
"github.com/restic/restic/internal/restic"
) )
// Config contains all configuration necessary to connect to a Google Cloud Storage // Config contains all configuration necessary to connect to a Google Cloud Storage
@ -58,11 +59,12 @@ func ParseConfig(s string) (*Config, error) {
return &cfg, nil return &cfg, nil
} }
var _ restic.ApplyEnvironmenter = &Config{}
// ApplyEnvironment saves values from the environment to the config. // ApplyEnvironment saves values from the environment to the config.
func ApplyEnvironment(cfgRaw interface{}) error { func (cfg *Config) ApplyEnvironment(prefix string) error {
cfg := cfgRaw.(*Config)
if cfg.ProjectID == "" { if cfg.ProjectID == "" {
cfg.ProjectID = os.Getenv("GOOGLE_PROJECT_ID") cfg.ProjectID = os.Getenv(prefix + "GOOGLE_PROJECT_ID")
} }
return nil return nil
} }

View File

@ -8,6 +8,7 @@ import (
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/options" "github.com/restic/restic/internal/options"
"github.com/restic/restic/internal/restic"
) )
// Config contains all configuration necessary to connect to an s3 compatible // Config contains all configuration necessary to connect to an s3 compatible
@ -93,15 +94,16 @@ func createConfig(endpoint, bucket, prefix string, useHTTP bool) (*Config, error
return &cfg, nil return &cfg, nil
} }
var _ restic.ApplyEnvironmenter = &Config{}
// ApplyEnvironment saves values from the environment to the config. // ApplyEnvironment saves values from the environment to the config.
func ApplyEnvironment(cfgRaw interface{}) error { func (cfg *Config) ApplyEnvironment(prefix string) error {
cfg := cfgRaw.(*Config)
if cfg.KeyID == "" { if cfg.KeyID == "" {
cfg.KeyID = os.Getenv("AWS_ACCESS_KEY_ID") cfg.KeyID = os.Getenv(prefix + "AWS_ACCESS_KEY_ID")
} }
if cfg.Secret.String() == "" { if cfg.Secret.String() == "" {
cfg.Secret = options.NewSecretString(os.Getenv("AWS_SECRET_ACCESS_KEY")) cfg.Secret = options.NewSecretString(os.Getenv(prefix + "AWS_SECRET_ACCESS_KEY"))
} }
if cfg.KeyID == "" && cfg.Secret.String() != "" { if cfg.KeyID == "" && cfg.Secret.String() != "" {
@ -111,7 +113,7 @@ func ApplyEnvironment(cfgRaw interface{}) error {
} }
if cfg.Region == "" { if cfg.Region == "" {
cfg.Region = os.Getenv("AWS_DEFAULT_REGION") cfg.Region = os.Getenv(prefix + "AWS_DEFAULT_REGION")
} }
return nil return nil

View File

@ -6,6 +6,7 @@ import (
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/options" "github.com/restic/restic/internal/options"
"github.com/restic/restic/internal/restic"
) )
// Config contains basic configuration needed to specify swift location for a swift server // Config contains basic configuration needed to specify swift location for a swift server
@ -73,45 +74,46 @@ func ParseConfig(s string) (*Config, error) {
return &cfg, nil return &cfg, nil
} }
var _ restic.ApplyEnvironmenter = &Config{}
// ApplyEnvironment saves values from the environment to the config. // ApplyEnvironment saves values from the environment to the config.
func ApplyEnvironment(prefix string, cfg interface{}) error { func (cfg *Config) ApplyEnvironment(prefix string) error {
c := cfg.(*Config)
for _, val := range []struct { for _, val := range []struct {
s *string s *string
env string env string
}{ }{
// v2/v3 specific // v2/v3 specific
{&c.UserName, prefix + "OS_USERNAME"}, {&cfg.UserName, prefix + "OS_USERNAME"},
{&c.APIKey, prefix + "OS_PASSWORD"}, {&cfg.APIKey, prefix + "OS_PASSWORD"},
{&c.Region, prefix + "OS_REGION_NAME"}, {&cfg.Region, prefix + "OS_REGION_NAME"},
{&c.AuthURL, prefix + "OS_AUTH_URL"}, {&cfg.AuthURL, prefix + "OS_AUTH_URL"},
// v3 specific // v3 specific
{&c.UserID, prefix + "OS_USER_ID"}, {&cfg.UserID, prefix + "OS_USER_ID"},
{&c.Domain, prefix + "OS_USER_DOMAIN_NAME"}, {&cfg.Domain, prefix + "OS_USER_DOMAIN_NAME"},
{&c.DomainID, prefix + "OS_USER_DOMAIN_ID"}, {&cfg.DomainID, prefix + "OS_USER_DOMAIN_ID"},
{&c.Tenant, prefix + "OS_PROJECT_NAME"}, {&cfg.Tenant, prefix + "OS_PROJECT_NAME"},
{&c.TenantDomain, prefix + "OS_PROJECT_DOMAIN_NAME"}, {&cfg.TenantDomain, prefix + "OS_PROJECT_DOMAIN_NAME"},
{&c.TenantDomainID, prefix + "OS_PROJECT_DOMAIN_ID"}, {&cfg.TenantDomainID, prefix + "OS_PROJECT_DOMAIN_ID"},
{&c.TrustID, prefix + "OS_TRUST_ID"}, {&cfg.TrustID, prefix + "OS_TRUST_ID"},
// v2 specific // v2 specific
{&c.TenantID, prefix + "OS_TENANT_ID"}, {&cfg.TenantID, prefix + "OS_TENANT_ID"},
{&c.Tenant, prefix + "OS_TENANT_NAME"}, {&cfg.Tenant, prefix + "OS_TENANT_NAME"},
// v1 specific // v1 specific
{&c.AuthURL, prefix + "ST_AUTH"}, {&cfg.AuthURL, prefix + "ST_AUTH"},
{&c.UserName, prefix + "ST_USER"}, {&cfg.UserName, prefix + "ST_USER"},
{&c.APIKey, prefix + "ST_KEY"}, {&cfg.APIKey, prefix + "ST_KEY"},
// Application Credential auth // Application Credential auth
{&c.ApplicationCredentialID, prefix + "OS_APPLICATION_CREDENTIAL_ID"}, {&cfg.ApplicationCredentialID, prefix + "OS_APPLICATION_CREDENTIAL_ID"},
{&c.ApplicationCredentialName, prefix + "OS_APPLICATION_CREDENTIAL_NAME"}, {&cfg.ApplicationCredentialName, prefix + "OS_APPLICATION_CREDENTIAL_NAME"},
// Manual authentication // Manual authentication
{&c.StorageURL, prefix + "OS_STORAGE_URL"}, {&cfg.StorageURL, prefix + "OS_STORAGE_URL"},
{&c.DefaultContainerPolicy, prefix + "SWIFT_DEFAULT_CONTAINER_POLICY"}, {&cfg.DefaultContainerPolicy, prefix + "SWIFT_DEFAULT_CONTAINER_POLICY"},
} { } {
if *val.s == "" { if *val.s == "" {
*val.s = os.Getenv(val.env) *val.s = os.Getenv(val.env)
@ -121,8 +123,8 @@ func ApplyEnvironment(prefix string, cfg interface{}) error {
s *options.SecretString s *options.SecretString
env string env string
}{ }{
{&c.ApplicationCredentialSecret, prefix + "OS_APPLICATION_CREDENTIAL_SECRET"}, {&cfg.ApplicationCredentialSecret, prefix + "OS_APPLICATION_CREDENTIAL_SECRET"},
{&c.AuthToken, prefix + "OS_AUTH_TOKEN"}, {&cfg.AuthToken, prefix + "OS_AUTH_TOKEN"},
} { } {
if val.s.String() == "" { if val.s.String() == "" {
*val.s = options.NewSecretString(os.Getenv(val.env)) *val.s = options.NewSecretString(os.Getenv(val.env))

View File

@ -48,7 +48,7 @@ func newSwiftTestSuite(t testing.TB) *test.Suite[swift.Config] {
return nil, err return nil, err
} }
if err = swift.ApplyEnvironment("RESTIC_TEST_", &cfg); err != nil { if err = cfg.ApplyEnvironment("RESTIC_TEST_"); err != nil {
return nil, err return nil, err
} }
cfg.Prefix += fmt.Sprintf("/test-%d", time.Now().UnixNano()) cfg.Prefix += fmt.Sprintf("/test-%d", time.Now().UnixNano())

View File

@ -80,3 +80,8 @@ type FileInfo struct {
Size int64 Size int64
Name string Name string
} }
// ApplyEnvironmenter fills in a backend configuration from the environment
type ApplyEnvironmenter interface {
ApplyEnvironment(prefix string) error
}