2017-03-29 21:58:25 +00:00
|
|
|
package swift
|
|
|
|
|
|
|
|
import (
|
2017-05-01 08:13:03 +00:00
|
|
|
"os"
|
|
|
|
"strings"
|
2017-07-23 12:21:03 +00:00
|
|
|
|
|
|
|
"github.com/restic/restic/internal/errors"
|
|
|
|
"github.com/restic/restic/internal/options"
|
2023-04-21 19:51:58 +00:00
|
|
|
"github.com/restic/restic/internal/restic"
|
2017-03-29 21:58:25 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Config contains basic configuration needed to specify swift location for a swift server
|
|
|
|
type Config struct {
|
2020-12-11 18:09:32 +00:00
|
|
|
UserName string
|
|
|
|
UserID string
|
|
|
|
Domain string
|
|
|
|
DomainID string
|
|
|
|
APIKey string
|
|
|
|
AuthURL string
|
|
|
|
Region string
|
|
|
|
Tenant string
|
|
|
|
TenantID string
|
|
|
|
TenantDomain string
|
|
|
|
TenantDomainID string
|
|
|
|
TrustID string
|
2017-03-29 21:58:25 +00:00
|
|
|
|
|
|
|
StorageURL string
|
2021-08-04 20:56:18 +00:00
|
|
|
AuthToken options.SecretString
|
2017-03-29 21:58:25 +00:00
|
|
|
|
2019-01-29 16:06:20 +00:00
|
|
|
// auth v3 only
|
|
|
|
ApplicationCredentialID string
|
|
|
|
ApplicationCredentialName string
|
2021-08-04 20:56:18 +00:00
|
|
|
ApplicationCredentialSecret options.SecretString
|
2019-01-29 16:06:20 +00:00
|
|
|
|
2017-03-29 21:58:25 +00:00
|
|
|
Container string
|
|
|
|
Prefix string
|
|
|
|
DefaultContainerPolicy string
|
2017-06-05 22:33:25 +00:00
|
|
|
|
2017-06-11 11:46:54 +00:00
|
|
|
Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 5)"`
|
2017-06-05 22:33:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
options.Register("swift", Config{})
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewConfig returns a new config with the default values filled in.
|
|
|
|
func NewConfig() Config {
|
|
|
|
return Config{
|
2017-06-11 11:46:54 +00:00
|
|
|
Connections: 5,
|
2017-06-05 22:33:25 +00:00
|
|
|
}
|
2017-03-29 21:58:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ParseConfig parses the string s and extract swift's container name and prefix.
|
2023-04-21 19:35:34 +00:00
|
|
|
func ParseConfig(s string) (*Config, error) {
|
2022-11-27 17:09:59 +00:00
|
|
|
if !strings.HasPrefix(s, "swift:") {
|
2023-04-21 19:35:34 +00:00
|
|
|
return nil, errors.New("invalid URL, expected: swift:container-name:/[prefix]")
|
2017-05-01 08:13:03 +00:00
|
|
|
}
|
2022-11-27 17:09:59 +00:00
|
|
|
s = strings.TrimPrefix(s, "swift:")
|
2017-03-29 21:58:25 +00:00
|
|
|
|
2022-11-27 17:09:59 +00:00
|
|
|
container, prefix, _ := strings.Cut(s, ":")
|
|
|
|
if prefix == "" {
|
2023-04-21 19:35:34 +00:00
|
|
|
return nil, errors.Errorf("prefix is empty")
|
2017-03-29 21:58:25 +00:00
|
|
|
}
|
|
|
|
|
2017-05-01 08:13:03 +00:00
|
|
|
if prefix[0] != '/' {
|
2023-04-21 19:35:34 +00:00
|
|
|
return nil, errors.Errorf("prefix does not start with slash (/)")
|
2017-05-01 08:13:03 +00:00
|
|
|
}
|
|
|
|
prefix = prefix[1:]
|
|
|
|
|
2017-06-05 22:33:25 +00:00
|
|
|
cfg := NewConfig()
|
|
|
|
cfg.Container = container
|
|
|
|
cfg.Prefix = prefix
|
2017-03-29 21:58:25 +00:00
|
|
|
|
2023-04-21 19:35:34 +00:00
|
|
|
return &cfg, nil
|
2017-03-29 21:58:25 +00:00
|
|
|
}
|
2017-05-01 08:13:03 +00:00
|
|
|
|
2023-04-21 19:51:58 +00:00
|
|
|
var _ restic.ApplyEnvironmenter = &Config{}
|
|
|
|
|
2017-05-01 08:13:03 +00:00
|
|
|
// ApplyEnvironment saves values from the environment to the config.
|
2023-06-08 13:28:07 +00:00
|
|
|
func (cfg *Config) ApplyEnvironment(prefix string) {
|
2017-05-01 08:13:03 +00:00
|
|
|
for _, val := range []struct {
|
|
|
|
s *string
|
|
|
|
env string
|
|
|
|
}{
|
|
|
|
// v2/v3 specific
|
2023-04-21 19:51:58 +00:00
|
|
|
{&cfg.UserName, prefix + "OS_USERNAME"},
|
|
|
|
{&cfg.APIKey, prefix + "OS_PASSWORD"},
|
|
|
|
{&cfg.Region, prefix + "OS_REGION_NAME"},
|
|
|
|
{&cfg.AuthURL, prefix + "OS_AUTH_URL"},
|
2017-05-01 08:13:03 +00:00
|
|
|
|
|
|
|
// v3 specific
|
2023-04-21 19:51:58 +00:00
|
|
|
{&cfg.UserID, prefix + "OS_USER_ID"},
|
|
|
|
{&cfg.Domain, prefix + "OS_USER_DOMAIN_NAME"},
|
|
|
|
{&cfg.DomainID, prefix + "OS_USER_DOMAIN_ID"},
|
|
|
|
{&cfg.Tenant, prefix + "OS_PROJECT_NAME"},
|
|
|
|
{&cfg.TenantDomain, prefix + "OS_PROJECT_DOMAIN_NAME"},
|
|
|
|
{&cfg.TenantDomainID, prefix + "OS_PROJECT_DOMAIN_ID"},
|
|
|
|
{&cfg.TrustID, prefix + "OS_TRUST_ID"},
|
2017-05-01 08:13:03 +00:00
|
|
|
|
|
|
|
// v2 specific
|
2023-04-21 19:51:58 +00:00
|
|
|
{&cfg.TenantID, prefix + "OS_TENANT_ID"},
|
|
|
|
{&cfg.Tenant, prefix + "OS_TENANT_NAME"},
|
2017-05-01 08:13:03 +00:00
|
|
|
|
|
|
|
// v1 specific
|
2023-04-21 19:51:58 +00:00
|
|
|
{&cfg.AuthURL, prefix + "ST_AUTH"},
|
|
|
|
{&cfg.UserName, prefix + "ST_USER"},
|
|
|
|
{&cfg.APIKey, prefix + "ST_KEY"},
|
2017-05-01 08:13:03 +00:00
|
|
|
|
2019-01-29 16:06:20 +00:00
|
|
|
// Application Credential auth
|
2023-04-21 19:51:58 +00:00
|
|
|
{&cfg.ApplicationCredentialID, prefix + "OS_APPLICATION_CREDENTIAL_ID"},
|
|
|
|
{&cfg.ApplicationCredentialName, prefix + "OS_APPLICATION_CREDENTIAL_NAME"},
|
2019-01-29 16:06:20 +00:00
|
|
|
|
2017-05-01 08:13:03 +00:00
|
|
|
// Manual authentication
|
2023-04-21 19:51:58 +00:00
|
|
|
{&cfg.StorageURL, prefix + "OS_STORAGE_URL"},
|
2017-05-01 08:13:03 +00:00
|
|
|
|
2023-04-21 19:51:58 +00:00
|
|
|
{&cfg.DefaultContainerPolicy, prefix + "SWIFT_DEFAULT_CONTAINER_POLICY"},
|
2017-05-01 08:13:03 +00:00
|
|
|
} {
|
|
|
|
if *val.s == "" {
|
|
|
|
*val.s = os.Getenv(val.env)
|
|
|
|
}
|
|
|
|
}
|
2021-08-04 20:56:18 +00:00
|
|
|
for _, val := range []struct {
|
|
|
|
s *options.SecretString
|
|
|
|
env string
|
|
|
|
}{
|
2023-04-21 19:51:58 +00:00
|
|
|
{&cfg.ApplicationCredentialSecret, prefix + "OS_APPLICATION_CREDENTIAL_SECRET"},
|
|
|
|
{&cfg.AuthToken, prefix + "OS_AUTH_TOKEN"},
|
2021-08-04 20:56:18 +00:00
|
|
|
} {
|
|
|
|
if val.s.String() == "" {
|
|
|
|
*val.s = options.NewSecretString(os.Getenv(val.env))
|
|
|
|
}
|
|
|
|
}
|
2017-05-01 08:13:03 +00:00
|
|
|
}
|