Try pathenvconfig

This commit is contained in:
MaxJa4
2023-08-27 22:29:44 +02:00
parent cc4492d2c0
commit 4c806006a4
4 changed files with 60 additions and 93 deletions

View File

@@ -16,86 +16,66 @@ import (
// Config holds all configuration values that are expected to be set
// by users.
type Config struct {
AwsS3BucketName string `env:"AWS_S3_BUCKET_NAME"`
AwsS3Path string `env:"AWS_S3_PATH"`
AwsEndpoint string `envDefault:"s3.amazonaws.com"`
AwsEndpointProto string `envDefault:"https"`
AwsS3BucketName string
AwsS3Path string
AwsEndpoint string `default:"s3.amazonaws.com"`
AwsEndpointProto string
AwsEndpointInsecure bool
AwsEndpointCACert CertDecoder `env:"AWS_ENDPOINT_CA_CERT"`
AwsEndpointCACert CertDecoder
AwsStorageClass string
AwsAccessKeyID string `env:"AWS_ACCESS_KEY_ID"`
AwsAccessKeyIDFile string `env:"AWS_ACCESS_KEY_ID_FILE,file"`
AwsSecretAccessKey string `env:"AWS_SECRET_ACCESS_KEY"`
AwsSecretAccessKeyFile string `env:"AWS_SECRET_ACCESS_KEY_FILE,file"`
AwsAccessKeyID string
AwsSecretAccessKey string
AwsIamRoleEndpoint string
AwsPartSize int64
BackupCompression CompressionType `envDefault:"gz"`
BackupSources string `envDefault:"/backup"`
BackupFilename string `envDefault:"backup-%Y-%m-%dT%H-%M-%S.{{ .Extension }}"`
BackupCompression CompressionType `default:"gz"`
BackupSources string `default:"/backup"`
BackupFilename string `default:"backup-%Y-%m-%dT%H-%M-%S.{{ .Extension }}"`
BackupFilenameExpand bool
BackupLatestSymlink string
BackupArchive string `envDefault:"/archive"`
BackupRetentionDays int32 `envDefault:"-1"`
BackupPruningLeeway time.Duration `envDefault:"1m"`
BackupArchive string `default:"/archive"`
BackupRetentionDays int32 `default:"-1"`
BackupPruningLeeway time.Duration `default:"1m"`
BackupPruningPrefix string
BackupStopContainerLabel string `envDefault:"true"`
BackupStopContainerLabel string `default:"true"`
BackupFromSnapshot bool
BackupExcludeRegexp RegexpDecoder
BackupSkipBackendsFromPrune []string
GpgPassphrase string `env:"GPG_PASSPHRASE"`
GpgPassphraseFile string `env:"GPG_PASSPHRASE_FILE,file"`
NotificationURLs []string `env:"NOTIFICATION_URLS"`
NotificationLevel string `envDefault:"error"`
GpgPassphrase string
NotificationURLs []string
NotificationLevel string `default:"error"`
EmailNotificationRecipient string
EmailNotificationSender string `envDefault:"noreply@nohost"`
EmailSMTPHost string `env:"EMAIL_SMTP_HOST"`
EmailSMTPPort int `env:"EMAIL_SMTP_PORT" envDefault:"587"`
EmailSMTPUsername string `env:"EMAIL_SMTP_USERNAME"`
EmailSMTPPassword string `env:"EMAIL_SMTP_PASSWORD"`
EmailSMTPPasswordFile string `env:"EMAIL_SMTP_PASSWORD_FILE,file"`
EmailNotificationSender string `default:"noreply@nohost"`
EmailSMTPHost string
EmailSMTPPort int `default:"587"`
EmailSMTPUsername string
EmailSMTPPassword string
WebdavUrl string
WebdavUrlInsecure bool
WebdavPath string `envDefault:"/"`
WebdavPath string `default:"/"`
WebdavUsername string
WebdavPassword string `env:"WEBDAV_PASSWORD"`
WebdavPasswordFile string `env:"WEBDAV_PASSWORD_FILE,file"`
SSHHostName string `env:"SSH_HOST_NAME"`
SSHPort string `env:"SSH_PORT" envDefault:"22"`
SSHUser string `env:"SSH_USER"`
SSHPassword string `env:"SSH_PASSWORD"`
SSHPasswordFile string `env:"SSH_PASSWORD_FILE,file"`
SSHIdentityFile string `env:"SSH_IDENTITY_FILE" envDefault:"/root/.ssh/id_rsa"`
SSHIdentityPassphrase string `env:"SSH_IDENTITY_PASSPHRASE"`
SSHIdentityPassphraseFile string `env:"SSH_IDENTITY_PASSPHRASE_FILE,file"`
SSHRemotePath string `env:"SSH_REMOTE_PATH"`
WebdavPassword string
SSHHostName string
SSHPort string `default:"22"`
SSHUser string
SSHPassword string
SSHIdentityFile string `default:"/root/.ssh/id_rsa"`
SSHIdentityPassphrase string
SSHRemotePath string
ExecLabel string
ExecForwardOutput bool
LockTimeout time.Duration `envDefault:"60m"`
LockTimeout time.Duration `default:"60m"`
AzureStorageAccountName string
AzureStoragePrimaryAccountKey string
AzureStorageContainerName string
AzureStoragePath string
AzureStorageEndpoint string `envDefault:"https://{{ .AccountName }}.blob.core.windows.net/"`
DropboxEndpoint string `envDefault:"https://api.dropbox.com/"`
DropboxOAuth2Endpoint string `env:"DROPBOX_OAUTH2_ENDPOINT" envDefault:"https://api.dropbox.com/"`
DropboxRefreshToken string `env:"DROPBOX_REFRESH_TOKEN"`
DropboxRefreshTokenFile string `env:"DROPBOX_REFRESH_TOKEN_FILE,file"`
DropboxAppKey string `env:"DROPBOX_APP_KEY"`
DropboxAppKeyFile string `env:"DROPBOX_APP_KEY_FILE,file"`
DropboxAppSecret string `env:"DROPBOX_APP_SECRET"`
DropboxAppSecretFile string `env:"DROPBOX_APP_SECRET_FILE,file"`
AzureStorageEndpoint string `default:"https://{{ .AccountName }}.blob.core.windows.net/"`
DropboxEndpoint string `default:"https://api.dropbox.com/"`
DropboxOAuth2Endpoint string `default:"https://api.dropbox.com/"`
DropboxRefreshToken string
DropboxAppKey string
DropboxAppSecret string
DropboxRemotePath string
DropboxConcurrencyLevel NaturalNumber `envDefault:"6"`
}
func (c *Config) getSecret(preferred string, fallback string) string {
if preferred != "" {
return preferred
}
if fallback != "" {
return fallback
}
return ""
DropboxConcurrencyLevel NaturalNumber `default:"6"`
}
type CompressionType string

View File

@@ -28,7 +28,6 @@ import (
"github.com/offen/docker-volume-backup/internal/storage/webdav"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/caarlos0/env/v9"
"github.com/containrrr/shoutrrr"
"github.com/containrrr/shoutrrr/pkg/router"
"github.com/docker/docker/api/types"
@@ -36,6 +35,7 @@ import (
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"github.com/johnstairs/pathenvconfig"
"github.com/leekchan/timeutil"
"github.com/otiai10/copy"
"golang.org/x/sync/errgroup"
@@ -89,13 +89,12 @@ func newScript() (*script, error) {
return nil
})
envOptions := env.Options{
UseFieldNameByDefault: true,
}
if err := env.ParseWithOptions(s.c, envOptions); err != nil {
if err := pathenvconfig.Process("", s.c); err != nil {
return nil, fmt.Errorf("newScript: failed to process configuration values: %w", err)
}
fmt.Printf("Using configuration: %+v\n", s.c) // Debug
s.file = path.Join("/tmp", s.c.BackupFilename)
tmplFileName, tErr := template.New("extension").Parse(s.file)
@@ -140,13 +139,10 @@ func newScript() (*script, error) {
}
if s.c.AwsS3BucketName != "" {
accessKeyID := s.c.getSecret(s.c.AwsAccessKeyIDFile, s.c.AwsAccessKeyID)
secretAccessKey := s.c.getSecret(s.c.AwsSecretAccessKeyFile, s.c.AwsSecretAccessKey)
s3Config := s3.Config{
Endpoint: s.c.AwsEndpoint,
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
AccessKeyID: s.c.AwsAccessKeyID,
SecretAccessKey: s.c.AwsSecretAccessKey,
IamRoleEndpoint: s.c.AwsIamRoleEndpoint,
EndpointProto: s.c.AwsEndpointProto,
EndpointInsecure: s.c.AwsEndpointInsecure,
@@ -164,13 +160,11 @@ func newScript() (*script, error) {
}
if s.c.WebdavUrl != "" {
webdavPassword := s.c.getSecret(s.c.WebdavPasswordFile, s.c.WebdavPassword)
webDavConfig := webdav.Config{
URL: s.c.WebdavUrl,
URLInsecure: s.c.WebdavUrlInsecure,
Username: s.c.WebdavUsername,
Password: webdavPassword,
Password: s.c.WebdavPassword,
RemotePath: s.c.WebdavPath,
}
if webdavBackend, err := webdav.NewStorageBackend(webDavConfig, logFunc); err != nil {
@@ -181,16 +175,13 @@ func newScript() (*script, error) {
}
if s.c.SSHHostName != "" {
sshPassword := s.c.getSecret(s.c.SSHPasswordFile, s.c.SSHPassword)
sshIdentityPassphrase := s.c.getSecret(s.c.SSHIdentityPassphraseFile, s.c.SSHIdentityPassphrase)
sshConfig := ssh.Config{
HostName: s.c.SSHHostName,
Port: s.c.SSHPort,
User: s.c.SSHUser,
Password: sshPassword,
Password: s.c.SSHPassword,
IdentityFile: s.c.SSHIdentityFile,
IdentityPassphrase: sshIdentityPassphrase,
IdentityPassphrase: s.c.SSHIdentityPassphrase,
RemotePath: s.c.SSHRemotePath,
}
if sshBackend, err := ssh.NewStorageBackend(sshConfig, logFunc); err != nil {
@@ -225,16 +216,12 @@ func newScript() (*script, error) {
}
if s.c.DropboxRefreshToken != "" && s.c.DropboxAppKey != "" && s.c.DropboxAppSecret != "" {
dropboxRefreshToken := s.c.getSecret(s.c.DropboxRefreshTokenFile, s.c.DropboxRefreshToken)
dropboxAppKey := s.c.getSecret(s.c.DropboxAppKeyFile, s.c.DropboxAppKey)
dropboxAppSecret := s.c.getSecret(s.c.DropboxAppSecretFile, s.c.DropboxAppSecret)
dropboxConfig := dropbox.Config{
Endpoint: s.c.DropboxEndpoint,
OAuth2Endpoint: s.c.DropboxOAuth2Endpoint,
RefreshToken: dropboxRefreshToken,
AppKey: dropboxAppKey,
AppSecret: dropboxAppSecret,
RefreshToken: s.c.DropboxRefreshToken,
AppKey: s.c.DropboxAppKey,
AppSecret: s.c.DropboxAppSecret,
RemotePath: s.c.DropboxRemotePath,
ConcurrencyLevel: s.c.DropboxConcurrencyLevel.Int(),
}
@@ -246,12 +233,10 @@ func newScript() (*script, error) {
}
if s.c.EmailNotificationRecipient != "" {
smtpPassword := s.c.getSecret(s.c.EmailSMTPPasswordFile, s.c.EmailSMTPPassword)
emailURL := fmt.Sprintf(
"smtp://%s:%s@%s:%d/?from=%s&to=%s",
s.c.EmailSMTPUsername,
smtpPassword,
s.c.EmailSMTPPassword,
s.c.EmailSMTPHost,
s.c.EmailSMTPPort,
s.c.EmailNotificationSender,
@@ -512,8 +497,7 @@ func (s *script) createArchive() error {
// In case no passphrase is given it returns early, leaving the backup file
// untouched.
func (s *script) encryptArchive() error {
gpgPassphrase := s.c.getSecret(s.c.GpgPassphraseFile, s.c.GpgPassphrase)
if gpgPassphrase == "" {
if s.c.GpgPassphrase == "" {
return nil
}
@@ -535,7 +519,7 @@ func (s *script) encryptArchive() error {
defer outFile.Close()
_, name := path.Split(s.file)
dst, err := openpgp.SymmetricallyEncrypt(outFile, []byte(gpgPassphrase), &openpgp.FileHints{
dst, err := openpgp.SymmetricallyEncrypt(outFile, []byte(s.c.GpgPassphrase), &openpgp.FileHints{
IsBinary: true,
FileName: name,
}, nil)