replace ark restic repo init cmd with automatic initialization of repos

Signed-off-by: Steve Kriss <steve@heptio.com>
This commit is contained in:
Steve Kriss
2018-06-27 13:50:37 -07:00
parent e015238e6d
commit 22e8f23e2c
19 changed files with 360 additions and 433 deletions
+29 -7
View File
@@ -17,6 +17,7 @@ limitations under the License.
package controller
import (
"context"
"encoding/json"
"time"
@@ -39,6 +40,8 @@ import (
"k8s.io/client-go/tools/cache"
)
const resticTimeout = time.Minute
type backupDeletionController struct {
*genericController
@@ -239,13 +242,9 @@ func (c *backupDeletionController) processRequest(req *v1.DeleteBackupRequest) e
// Try to delete restic snapshots
log.Info("Removing restic snapshots")
if snapshots, err := restic.GetSnapshotsInBackup(backup, c.podvolumeBackupLister); err != nil {
errs = append(errs, err.Error())
} else {
for _, snapshot := range snapshots {
if err := c.resticMgr.Forget(snapshot); err != nil {
errs = append(errs, err.Error())
}
if deleteErrs := c.deleteResticSnapshots(backup); len(deleteErrs) > 0 {
for _, err := range deleteErrs {
errs = append(errs, err.Error())
}
}
@@ -304,6 +303,29 @@ func (c *backupDeletionController) processRequest(req *v1.DeleteBackupRequest) e
return nil
}
func (c *backupDeletionController) deleteResticSnapshots(backup *v1.Backup) []error {
if c.resticMgr == nil {
return nil
}
snapshots, err := restic.GetSnapshotsInBackup(backup, c.podvolumeBackupLister)
if err != nil {
return []error{err}
}
ctx, cancelFunc := context.WithTimeout(context.Background(), resticTimeout)
defer cancelFunc()
var errs []error
for _, snapshot := range snapshots {
if err := c.resticMgr.Forget(ctx, snapshot); err != nil {
errs = append(errs, err)
}
}
return errs
}
const deleteBackupRequestMaxAge = 24 * time.Hour
func (c *backupDeletionController) deleteExpiredRequests() {
@@ -60,7 +60,7 @@ func NewPodVolumeBackupController(
podVolumeBackupInformer informers.PodVolumeBackupInformer,
podVolumeBackupClient arkv1client.PodVolumeBackupsGetter,
podInformer cache.SharedIndexInformer,
secretInformer corev1informers.SecretInformer,
secretInformer cache.SharedIndexInformer,
pvcInformer corev1informers.PersistentVolumeClaimInformer,
nodeName string,
) Interface {
@@ -69,7 +69,7 @@ func NewPodVolumeBackupController(
podVolumeBackupClient: podVolumeBackupClient,
podVolumeBackupLister: podVolumeBackupInformer.Lister(),
podLister: corev1listers.NewPodLister(podInformer.GetIndexer()),
secretLister: secretInformer.Lister(),
secretLister: corev1listers.NewSecretLister(secretInformer.GetIndexer()),
pvcLister: pvcInformer.Lister(),
nodeName: nodeName,
}
@@ -78,8 +78,8 @@ func NewPodVolumeBackupController(
c.cacheSyncWaiters = append(
c.cacheSyncWaiters,
podVolumeBackupInformer.Informer().HasSynced,
secretInformer.Informer().HasSynced,
podInformer.HasSynced,
secretInformer.HasSynced,
pvcInformer.Informer().HasSynced,
)
c.processBackupFunc = c.processBackup
@@ -194,7 +194,7 @@ func (c *podVolumeBackupController) processBackup(req *arkv1api.PodVolumeBackup)
log.WithField("path", path).Debugf("Found path matching glob")
// temp creds
file, err := restic.TempCredentialsFile(c.secretLister, req.Spec.Pod.Namespace)
file, err := restic.TempCredentialsFile(c.secretLister, req.Namespace, req.Spec.Pod.Namespace)
if err != nil {
log.WithError(err).Error("Error creating temp restic credentials file")
return c.fail(req, errors.Wrap(err, "error creating temp restic credentials file").Error(), log)
@@ -50,8 +50,8 @@ type podVolumeRestoreController struct {
podVolumeRestoreClient arkv1client.PodVolumeRestoresGetter
podVolumeRestoreLister listers.PodVolumeRestoreLister
secretLister corev1listers.SecretLister
podLister corev1listers.PodLister
secretLister corev1listers.SecretLister
pvcLister corev1listers.PersistentVolumeClaimLister
nodeName string
@@ -64,7 +64,7 @@ func NewPodVolumeRestoreController(
podVolumeRestoreInformer informers.PodVolumeRestoreInformer,
podVolumeRestoreClient arkv1client.PodVolumeRestoresGetter,
podInformer cache.SharedIndexInformer,
secretInformer corev1informers.SecretInformer,
secretInformer cache.SharedIndexInformer,
pvcInformer corev1informers.PersistentVolumeClaimInformer,
nodeName string,
) Interface {
@@ -73,7 +73,7 @@ func NewPodVolumeRestoreController(
podVolumeRestoreClient: podVolumeRestoreClient,
podVolumeRestoreLister: podVolumeRestoreInformer.Lister(),
podLister: corev1listers.NewPodLister(podInformer.GetIndexer()),
secretLister: secretInformer.Lister(),
secretLister: corev1listers.NewSecretLister(secretInformer.GetIndexer()),
pvcLister: pvcInformer.Lister(),
nodeName: nodeName,
}
@@ -82,8 +82,8 @@ func NewPodVolumeRestoreController(
c.cacheSyncWaiters = append(
c.cacheSyncWaiters,
podVolumeRestoreInformer.Informer().HasSynced,
secretInformer.Informer().HasSynced,
podInformer.HasSynced,
secretInformer.HasSynced,
pvcInformer.Informer().HasSynced,
)
c.processRestoreFunc = c.processRestore
@@ -270,7 +270,7 @@ func (c *podVolumeRestoreController) processRestore(req *arkv1api.PodVolumeResto
return c.failRestore(req, errors.Wrap(err, "error getting volume directory name").Error(), log)
}
credsFile, err := restic.TempCredentialsFile(c.secretLister, req.Spec.Pod.Namespace)
credsFile, err := restic.TempCredentialsFile(c.secretLister, req.Namespace, req.Spec.Pod.Namespace)
if err != nil {
log.WithError(err).Error("Error creating temp restic credentials file")
return c.failRestore(req, errors.Wrap(err, "error creating temp restic credentials file").Error(), log)
@@ -148,7 +148,7 @@ func (c *resticRepositoryController) initializeRepo(req *v1.ResticRepository, lo
return err
}
if err := ensureRepo(req.Name, c.repositoryManager); err != nil {
if err := ensureRepo(req.Name, req.Spec.ResticIdentifier, c.repositoryManager); err != nil {
return c.patchResticRepository(req, repoNotReady(err.Error()))
}
@@ -160,12 +160,12 @@ func (c *resticRepositoryController) initializeRepo(req *v1.ResticRepository, lo
// ensureRepo first checks the repo, and returns if check passes. If it fails,
// attempts to init the repo, and returns the result.
func ensureRepo(name string, repoManager restic.RepositoryManager) error {
if repoManager.CheckRepo(name) == nil {
func ensureRepo(name, identifier string, repoManager restic.RepositoryManager) error {
if repoManager.CheckRepo(name, identifier) == nil {
return nil
}
return repoManager.InitRepo(name)
return repoManager.InitRepo(name, identifier)
}
func (c *resticRepositoryController) runMaintenanceIfDue(req *v1.ResticRepository, log logrus.FieldLogger) error {
@@ -181,14 +181,14 @@ func (c *resticRepositoryController) runMaintenanceIfDue(req *v1.ResticRepositor
log.Info("Running maintenance on restic repository")
log.Debug("Checking repo before prune")
if err := c.repositoryManager.CheckRepo(req.Name); err != nil {
if err := c.repositoryManager.CheckRepo(req.Name, req.Spec.ResticIdentifier); err != nil {
return c.patchResticRepository(req, repoNotReady(err.Error()))
}
// prune failures should be displayed in the `.status.message` field but
// should not cause the repo to move to `NotReady`.
log.Debug("Pruning repo")
if err := c.repositoryManager.PruneRepo(req.Name); err != nil {
if err := c.repositoryManager.PruneRepo(req.Name, req.Spec.ResticIdentifier); err != nil {
log.WithError(err).Warn("error pruning repository")
if patchErr := c.patchResticRepository(req, func(r *v1.ResticRepository) {
r.Status.Message = err.Error()
@@ -198,7 +198,7 @@ func (c *resticRepositoryController) runMaintenanceIfDue(req *v1.ResticRepositor
}
log.Debug("Checking repo after prune")
if err := c.repositoryManager.CheckRepo(req.Name); err != nil {
if err := c.repositoryManager.CheckRepo(req.Name, req.Spec.ResticIdentifier); err != nil {
return c.patchResticRepository(req, repoNotReady(err.Error()))
}
@@ -216,7 +216,7 @@ func (c *resticRepositoryController) checkNotReadyRepo(req *v1.ResticRepository,
// we need to ensure it (first check, if check fails, attempt to init)
// because we don't know if it's been successfully initialized yet.
if err := ensureRepo(req.Name, c.repositoryManager); err != nil {
if err := ensureRepo(req.Name, req.Spec.ResticIdentifier, c.repositoryManager); err != nil {
return c.patchResticRepository(req, repoNotReady(err.Error()))
}