Merge pull request #3819 from lbausch/restore-validate-patterns
restore: validate include/exclude patterns
This commit is contained in:
commit
3934480da4
4 changed files with 75 additions and 0 deletions
10
changelog/unreleased/pull-3819
Normal file
10
changelog/unreleased/pull-3819
Normal file
|
@ -0,0 +1,10 @@
|
|||
Enhancement: Validate include/exclude patterns before restoring
|
||||
|
||||
Patterns provided to `restic restore` via `--exclude`, `--iexclude`,
|
||||
`--include` and `--iinclude` weren't validated before running the restore.
|
||||
Invalid patterns would result in error messages being printed repeatedly
|
||||
and possibly unwanted files being restored.
|
||||
restic now validates all patterns before running the restore and aborts with
|
||||
a fatal error if an invalid pattern is detected.
|
||||
|
||||
https://github.com/restic/restic/pull/3819
|
|
@ -70,6 +70,28 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error {
|
|||
hasExcludes := len(opts.Exclude) > 0 || len(opts.InsensitiveExclude) > 0
|
||||
hasIncludes := len(opts.Include) > 0 || len(opts.InsensitiveInclude) > 0
|
||||
|
||||
// Validate provided patterns
|
||||
if len(opts.Exclude) > 0 {
|
||||
if valid, invalidPatterns := filter.ValidatePatterns(opts.Exclude); !valid {
|
||||
return errors.Fatalf("--exclude: invalid pattern(s) provided:\n%s", strings.Join(invalidPatterns, "\n"))
|
||||
}
|
||||
}
|
||||
if len(opts.InsensitiveExclude) > 0 {
|
||||
if valid, invalidPatterns := filter.ValidatePatterns(opts.InsensitiveExclude); !valid {
|
||||
return errors.Fatalf("--iexclude: invalid pattern(s) provided:\n%s", strings.Join(invalidPatterns, "\n"))
|
||||
}
|
||||
}
|
||||
if len(opts.Include) > 0 {
|
||||
if valid, invalidPatterns := filter.ValidatePatterns(opts.Include); !valid {
|
||||
return errors.Fatalf("--include: invalid pattern(s) provided:\n%s", strings.Join(invalidPatterns, "\n"))
|
||||
}
|
||||
}
|
||||
if len(opts.InsensitiveInclude) > 0 {
|
||||
if valid, invalidPatterns := filter.ValidatePatterns(opts.InsensitiveInclude); !valid {
|
||||
return errors.Fatalf("--iinclude: invalid pattern(s) provided:\n%s", strings.Join(invalidPatterns, "\n"))
|
||||
}
|
||||
}
|
||||
|
||||
for i, str := range opts.InsensitiveExclude {
|
||||
opts.InsensitiveExclude[i] = strings.ToLower(str)
|
||||
}
|
||||
|
|
|
@ -67,3 +67,40 @@ func TestBackupFailsWhenUsingInvalidPatternsFromFile(t *testing.T) {
|
|||
*[._]log[.-][0-9]
|
||||
!*[._]log[.-][0-9]`, err.Error())
|
||||
}
|
||||
|
||||
func TestRestoreFailsWhenUsingInvalidPatterns(t *testing.T) {
|
||||
env, cleanup := withTestEnvironment(t)
|
||||
defer cleanup()
|
||||
|
||||
testRunInit(t, env.gopts)
|
||||
|
||||
var err error
|
||||
|
||||
// Test --exclude
|
||||
err = testRunRestoreAssumeFailure(t, "latest", RestoreOptions{Exclude: []string{"*[._]log[.-][0-9]", "!*[._]log[.-][0-9]"}}, env.gopts)
|
||||
|
||||
rtest.Equals(t, `Fatal: --exclude: invalid pattern(s) provided:
|
||||
*[._]log[.-][0-9]
|
||||
!*[._]log[.-][0-9]`, err.Error())
|
||||
|
||||
// Test --iexclude
|
||||
err = testRunRestoreAssumeFailure(t, "latest", RestoreOptions{InsensitiveExclude: []string{"*[._]log[.-][0-9]", "!*[._]log[.-][0-9]"}}, env.gopts)
|
||||
|
||||
rtest.Equals(t, `Fatal: --iexclude: invalid pattern(s) provided:
|
||||
*[._]log[.-][0-9]
|
||||
!*[._]log[.-][0-9]`, err.Error())
|
||||
|
||||
// Test --include
|
||||
err = testRunRestoreAssumeFailure(t, "latest", RestoreOptions{Include: []string{"*[._]log[.-][0-9]", "!*[._]log[.-][0-9]"}}, env.gopts)
|
||||
|
||||
rtest.Equals(t, `Fatal: --include: invalid pattern(s) provided:
|
||||
*[._]log[.-][0-9]
|
||||
!*[._]log[.-][0-9]`, err.Error())
|
||||
|
||||
// Test --iinclude
|
||||
err = testRunRestoreAssumeFailure(t, "latest", RestoreOptions{InsensitiveInclude: []string{"*[._]log[.-][0-9]", "!*[._]log[.-][0-9]"}}, env.gopts)
|
||||
|
||||
rtest.Equals(t, `Fatal: --iinclude: invalid pattern(s) provided:
|
||||
*[._]log[.-][0-9]
|
||||
!*[._]log[.-][0-9]`, err.Error())
|
||||
}
|
||||
|
|
|
@ -131,6 +131,12 @@ func testRunRestoreIncludes(t testing.TB, gopts GlobalOptions, dir string, snaps
|
|||
rtest.OK(t, runRestore(opts, gopts, []string{snapshotID.String()}))
|
||||
}
|
||||
|
||||
func testRunRestoreAssumeFailure(t testing.TB, snapshotID string, opts RestoreOptions, gopts GlobalOptions) error {
|
||||
err := runRestore(opts, gopts, []string{snapshotID})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func testRunCheck(t testing.TB, gopts GlobalOptions) {
|
||||
opts := CheckOptions{
|
||||
ReadData: true,
|
||||
|
|
Loading…
Reference in a new issue