mirror of
https://github.com/offen/docker-volume-backup.git
synced 2024-11-21 21:10:26 +01:00
Values without a backing env var should not be expanded (#368)
* Values without a backing env var should not be expanded * Add unit tests for sourcing behavior * Replace godotenv with shell lib
This commit is contained in:
parent
f64aaa6e24
commit
911fc5a223
21
.github/workflows/unit.yml
vendored
Normal file
21
.github/workflows/unit.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
name: Run Unit Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.22.x'
|
||||
- name: Install dependencies
|
||||
run: go mod download
|
||||
- name: Test with the Go CLI
|
||||
run: go test -v ./...
|
@ -4,13 +4,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/offen/docker-volume-backup/internal/errwrap"
|
||||
"github.com/offen/envconfig"
|
||||
"mvdan.cc/sh/shell"
|
||||
)
|
||||
|
||||
type configStrategy string
|
||||
@ -99,11 +100,7 @@ func loadConfigsFromEnvFiles(directory string) ([]*Config, error) {
|
||||
continue
|
||||
}
|
||||
p := filepath.Join(directory, item.Name())
|
||||
f, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrap(err, fmt.Sprintf("error reading %s", item.Name()))
|
||||
}
|
||||
envFile, err := godotenv.Unmarshal(os.ExpandEnv(string(f)))
|
||||
envFile, err := source(p)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrap(err, fmt.Sprintf("error reading config file %s", p))
|
||||
}
|
||||
@ -125,3 +122,17 @@ func loadConfigsFromEnvFiles(directory string) ([]*Config, error) {
|
||||
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
// source tries to mimic the pre v2.37.0 behavior of calling
|
||||
// `set +a; source $path; set -a` and returns the env vars as a map
|
||||
func source(path string) (map[string]string, error) {
|
||||
vars, err := shell.SourceFile(context.Background(), path)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrap(err, "error sourcing conf file")
|
||||
}
|
||||
result := map[string]string{}
|
||||
for key, value := range vars {
|
||||
result[key] = value.String()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
68
cmd/backup/config_provider_test.go
Normal file
68
cmd/backup/config_provider_test.go
Normal file
@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSource(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expectError bool
|
||||
expectedOutput map[string]string
|
||||
}{
|
||||
{
|
||||
"default",
|
||||
"testdata/default.env",
|
||||
false,
|
||||
map[string]string{
|
||||
"FOO": "bar",
|
||||
"BAZ": "qux",
|
||||
},
|
||||
},
|
||||
{
|
||||
"not found",
|
||||
"testdata/nope.env",
|
||||
true,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"braces",
|
||||
"testdata/braces.env",
|
||||
false,
|
||||
map[string]string{
|
||||
"FOO": "qux",
|
||||
"BAR": "xxx",
|
||||
"BAZ": "",
|
||||
},
|
||||
},
|
||||
{
|
||||
"expansion",
|
||||
"testdata/expansion.env",
|
||||
false,
|
||||
map[string]string{
|
||||
"BAR": "xxx",
|
||||
"FOO": "xxx",
|
||||
"BAZ": "xxx",
|
||||
"QUX": "yyy",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
os.Setenv("QUX", "yyy")
|
||||
defer os.Unsetenv("QUX")
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
result, err := source(test.input)
|
||||
if (err != nil) != test.expectError {
|
||||
t.Errorf("Unexpected error value %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(test.expectedOutput, result) {
|
||||
t.Errorf("Expected %v, got %v", test.expectedOutput, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
3
cmd/backup/testdata/braces.env
vendored
Normal file
3
cmd/backup/testdata/braces.env
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
FOO=${bar:-qux}
|
||||
BAR=xxx
|
||||
BAZ=$NOPE
|
2
cmd/backup/testdata/default.env
vendored
Normal file
2
cmd/backup/testdata/default.env
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
FOO=bar
|
||||
BAZ=qux
|
4
cmd/backup/testdata/expansion.env
vendored
Normal file
4
cmd/backup/testdata/expansion.env
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
BAR=xxx
|
||||
FOO=${BAR}
|
||||
BAZ=$BAR
|
||||
QUX=${QUX}
|
3
go.mod
3
go.mod
@ -10,7 +10,6 @@ require (
|
||||
github.com/docker/cli v24.0.9+incompatible
|
||||
github.com/docker/docker v24.0.7+incompatible
|
||||
github.com/gofrs/flock v0.8.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/klauspost/compress v1.17.6
|
||||
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d
|
||||
github.com/minio/minio-go/v7 v7.0.67
|
||||
@ -22,6 +21,7 @@ require (
|
||||
golang.org/x/crypto v0.19.0
|
||||
golang.org/x/oauth2 v0.17.0
|
||||
golang.org/x/sync v0.6.0
|
||||
mvdan.cc/sh v2.6.4+incompatible
|
||||
)
|
||||
|
||||
require (
|
||||
@ -29,6 +29,7 @@ require (
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
golang.org/x/term v0.17.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
|
6
go.sum
6
go.sum
@ -443,8 +443,6 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jarcoal/httpmock v1.2.0 h1:gSvTxxFR/MEMfsGrvRbdfpRUMBStovlSRLw0Ep1bwwc=
|
||||
github.com/jarcoal/httpmock v1.2.0/go.mod h1:oCoTsnAz4+UoOUIf5lJOWV2QQIW5UoeUI6aM2YnWAZk=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
@ -473,6 +471,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
@ -599,6 +598,7 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
@ -1259,6 +1259,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
mvdan.cc/sh v2.6.4+incompatible h1:eD6tDeh0pw+/TOTI1BBEryZ02rD2nMcFsgcvde7jffM=
|
||||
mvdan.cc/sh v2.6.4+incompatible/go.mod h1:IeeQbZq+x2SUGBensq/jge5lLQbS3XT2ktyp3wrt4x8=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
@ -1,2 +1,3 @@
|
||||
NAME="other"
|
||||
BACKUP_CRON_EXPRESSION="*/1 * * * *"
|
||||
BACKUP_FILENAME="override-$NAME.tar.gz"
|
||||
|
@ -20,7 +20,7 @@ if [ ! -f "$LOCAL_DIR/conf.tar.gz" ]; then
|
||||
fi
|
||||
pass "Config from file was used."
|
||||
|
||||
if [ ! -f "$LOCAL_DIR/other.tar.gz" ]; then
|
||||
if [ ! -f "$LOCAL_DIR/override-other.tar.gz" ]; then
|
||||
fail "Run on same schedule did not succeed."
|
||||
fi
|
||||
pass "Run on same schedule succeeded."
|
||||
|
Loading…
Reference in New Issue
Block a user