mirror of
https://github.com/restic/restic.git
synced 2026-09-26 14:00:29 +00:00
Add repositoryFile2 option
The `init` and `copy` commands can now use `--repository-file2` flag and the `$RESTIC_REPOSITORY_FILE2` environment variable. This also fixes the conflict with the `--repository-file` and `--repo2` flag. Tests are added for the initSecondaryGlobalOpts function. This adds a NOK function to the test helper functions. This NOK tests if err is not nil, and otherwise fail the test. With the NOK function a couple of sad paths are tested in the initSecondaryGlobalOpts function. In total the tests checks wether the following are passed correct: - Password - PasswordFile - Repo - RepositoryFile The following situation must return an error to pass the test: - no Repo or RepositoryFile defined - Repo and RepositoryFile defined both
This commit is contained in:
committed by
Michael Eischer
parent
d686fa25de
commit
9ccdba9df6
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
type secondaryRepoOptions struct {
|
||||
Repo string
|
||||
RepositoryFile string
|
||||
password string
|
||||
PasswordFile string
|
||||
PasswordCommand string
|
||||
@@ -17,18 +18,25 @@ type secondaryRepoOptions struct {
|
||||
|
||||
func initSecondaryRepoOptions(f *pflag.FlagSet, opts *secondaryRepoOptions, repoPrefix string, repoUsage string) {
|
||||
f.StringVarP(&opts.Repo, "repo2", "", os.Getenv("RESTIC_REPOSITORY2"), repoPrefix+" `repository` "+repoUsage+" (default: $RESTIC_REPOSITORY2)")
|
||||
f.StringVarP(&opts.RepositoryFile, "repository-file2", "", os.Getenv("RESTIC_REPOSITORY_FILE2"), "`file` from which to read the "+repoPrefix+" repository location "+repoUsage+" (default: $RESTIC_REPOSITORY_FILE2)")
|
||||
f.StringVarP(&opts.PasswordFile, "password-file2", "", os.Getenv("RESTIC_PASSWORD_FILE2"), "`file` to read the "+repoPrefix+" repository password from (default: $RESTIC_PASSWORD_FILE2)")
|
||||
f.StringVarP(&opts.KeyHint, "key-hint2", "", os.Getenv("RESTIC_KEY_HINT2"), "key ID of key to try decrypting the "+repoPrefix+" repository first (default: $RESTIC_KEY_HINT2)")
|
||||
f.StringVarP(&opts.PasswordCommand, "password-command2", "", os.Getenv("RESTIC_PASSWORD_COMMAND2"), "shell `command` to obtain the "+repoPrefix+" repository password from (default: $RESTIC_PASSWORD_COMMAND2)")
|
||||
}
|
||||
|
||||
func fillSecondaryGlobalOpts(opts secondaryRepoOptions, gopts GlobalOptions, repoPrefix string) (GlobalOptions, error) {
|
||||
if opts.Repo == "" {
|
||||
return GlobalOptions{}, errors.Fatal("Please specify a " + repoPrefix + " repository location (--repo2)")
|
||||
if opts.Repo == "" && opts.RepositoryFile == "" {
|
||||
return GlobalOptions{}, errors.Fatal("Please specify a " + repoPrefix + " repository location (--repo2 or --repository-file2)")
|
||||
}
|
||||
|
||||
if opts.Repo != "" && opts.RepositoryFile != "" {
|
||||
return GlobalOptions{}, errors.Fatal("Options --repo2 and --repository-file2 are mutually exclusive, please specify only one")
|
||||
}
|
||||
|
||||
var err error
|
||||
dstGopts := gopts
|
||||
dstGopts.Repo = opts.Repo
|
||||
dstGopts.RepositoryFile = opts.RepositoryFile
|
||||
dstGopts.PasswordFile = opts.PasswordFile
|
||||
dstGopts.PasswordCommand = opts.PasswordCommand
|
||||
dstGopts.KeyHint = opts.KeyHint
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
rtest "github.com/restic/restic/internal/test"
|
||||
)
|
||||
|
||||
//TestFillSecondaryGlobalOpts tests valid and invalid data on fillSecondaryGlobalOpts-function
|
||||
func TestFillSecondaryGlobalOpts(t *testing.T) {
|
||||
//secondaryRepoTestCase defines a struct for test cases
|
||||
type secondaryRepoTestCase struct {
|
||||
Opts secondaryRepoOptions
|
||||
DstGOpts GlobalOptions
|
||||
}
|
||||
|
||||
//validSecondaryRepoTestCases is a list with test cases that must pass
|
||||
var validSecondaryRepoTestCases = []secondaryRepoTestCase{
|
||||
{
|
||||
// Test if Repo and Password are parsed correctly.
|
||||
Opts: secondaryRepoOptions{
|
||||
Repo: "backupDst",
|
||||
password: "secretDst",
|
||||
},
|
||||
DstGOpts: GlobalOptions{
|
||||
Repo: "backupDst",
|
||||
password: "secretDst",
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test if RepositoryFile and PasswordFile are parsed correctly.
|
||||
Opts: secondaryRepoOptions{
|
||||
RepositoryFile: "backupDst",
|
||||
PasswordFile: "passwordFileDst",
|
||||
},
|
||||
DstGOpts: GlobalOptions{
|
||||
RepositoryFile: "backupDst",
|
||||
password: "secretDst",
|
||||
PasswordFile: "passwordFileDst",
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test if RepositoryFile and PasswordFile are parsed correctly.
|
||||
Opts: secondaryRepoOptions{
|
||||
RepositoryFile: "backupDst",
|
||||
PasswordCommand: "echo secretDst",
|
||||
},
|
||||
DstGOpts: GlobalOptions{
|
||||
RepositoryFile: "backupDst",
|
||||
password: "secretDst",
|
||||
PasswordCommand: "echo secretDst",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
//invalidSecondaryRepoTestCases is a list with test cases that must fail
|
||||
var invalidSecondaryRepoTestCases = []secondaryRepoTestCase{
|
||||
{
|
||||
// Test must fail on no repo given.
|
||||
Opts: secondaryRepoOptions{},
|
||||
},
|
||||
{
|
||||
// Test must fail as Repo and RepositoryFile are both given
|
||||
Opts: secondaryRepoOptions{
|
||||
Repo: "backupDst",
|
||||
RepositoryFile: "backupDst",
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test must fail on no repo given.
|
||||
Opts: secondaryRepoOptions{
|
||||
Repo: "backupDst",
|
||||
PasswordFile: "passwordFileDst",
|
||||
PasswordCommand: "notEmpty",
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test must fail on no repo given.
|
||||
Opts: secondaryRepoOptions{
|
||||
Repo: "backupDst",
|
||||
PasswordFile: "NonExistingFile",
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test must fail on no repo given.
|
||||
Opts: secondaryRepoOptions{
|
||||
Repo: "backupDst",
|
||||
PasswordCommand: "notEmpty",
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test must fail on no repo given.
|
||||
Opts: secondaryRepoOptions{
|
||||
Repo: "backupDst",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
//gOpts defines the Global options used in the secondary repository tests
|
||||
var gOpts = GlobalOptions{
|
||||
Repo: "backupSrc",
|
||||
RepositoryFile: "backupSrc",
|
||||
password: "secretSrc",
|
||||
PasswordFile: "passwordFileSrc",
|
||||
}
|
||||
|
||||
//Create temp dir to create password file.
|
||||
dir, cleanup := rtest.TempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
cleanup = rtest.Chdir(t, dir)
|
||||
defer cleanup()
|
||||
|
||||
//Create temporary password file
|
||||
err := ioutil.WriteFile(filepath.Join(dir, "passwordFileDst"), []byte("secretDst"), 0666)
|
||||
rtest.OK(t, err)
|
||||
|
||||
// Test all valid cases
|
||||
for _, testCase := range validSecondaryRepoTestCases {
|
||||
DstGOpts, err := fillSecondaryGlobalOpts(testCase.Opts, gOpts, "destination")
|
||||
rtest.OK(t, err)
|
||||
rtest.Equals(t, DstGOpts, testCase.DstGOpts)
|
||||
}
|
||||
|
||||
// Test all invalid cases
|
||||
for _, testCase := range invalidSecondaryRepoTestCases {
|
||||
_, err := fillSecondaryGlobalOpts(testCase.Opts, gOpts, "destination")
|
||||
rtest.Assert(t, err != nil, "Expected error, but function did not return an error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user