move dotfiles from staging to volume dir on restore

Signed-off-by: Steve Kriss <steve@heptio.com>
This commit is contained in:
Steve Kriss
2018-06-08 13:26:59 -07:00
parent e354b1c130
commit 6897c2f901

View File

@@ -23,6 +23,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strings"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
@@ -329,8 +330,13 @@ func restorePodVolume(req *arkv1api.PodVolumeRestore, credsFile, volumeDir strin
// giving errors about renames not being allowed across filesystem layers in a container. This is occurring
// whether /restores is part of the writeable container layer, or is an emptyDir volume mount. This may
// be solvable but using the shell works so not investigating further.
if _, stderr, err := runCommand(exec.Command("/bin/sh", "-c", fmt.Sprintf("mv %s/* %s/", restorePath, volumePath))); err != nil {
return errors.Wrapf(err, "error moving contents of restore staging directory into volume, stderr=%s", stderr)
//
// Glob patterns:
// [^.]* : any non-dot character followed by anything (regular files)
// .[^.]* : a dot followed by a non-dot and anything else (dotfiles starting with a single dot, excluding '.')
// ..?* : two dots followed by any single character and anything else (dotfiles starting with two dots, excluding '..')
if err := moveMatchingFiles(restorePath, volumePath, "[^.]*", ".[^.]*", "..?*"); err != nil {
return errors.Wrapf(err, "error moving files from restore staging directory into volume")
}
// The staging directory should be empty at this point since we moved everything, but
@@ -365,6 +371,38 @@ func restorePodVolume(req *arkv1api.PodVolumeRestore, credsFile, volumeDir strin
return nil
}
func moveMatchingFiles(sourceDir, destinationDir string, patterns ...string) error {
// find the patterns that match at least one file
var matchingPatterns []string
for _, pattern := range patterns {
fullPattern := fmt.Sprintf("%s/%s", sourceDir, pattern)
files, err := filepath.Glob(fullPattern)
if err != nil {
return errors.Wrapf(err, "error finding matches for pattern %s", pattern)
}
if len(files) > 0 {
matchingPatterns = append(matchingPatterns, fullPattern)
}
}
// if no patterns matched any files, we're done
if len(matchingPatterns) == 0 {
return nil
}
// we only use patterns that matched 1+ file(s) because mv returns an error on a pattern
// that doesn't match anything.
cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("mv %s %s", strings.Join(matchingPatterns, " "), destinationDir+"/"))
if _, stderr, err := runCommand(cmd); err != nil {
return errors.Wrapf(err, "error moving files from restore staging directory into volume, stderr=%s", stderr)
}
return nil
}
func (c *podVolumeRestoreController) patchPodVolumeRestore(req *arkv1api.PodVolumeRestore, mutate func(*arkv1api.PodVolumeRestore)) (*arkv1api.PodVolumeRestore, error) {
// Record original json
oldData, err := json.Marshal(req)