This repository has been archived by the owner on Aug 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #201 from JohnStrunk/refactor3
Create mover Interface to start isolating mover code
- Loading branch information
Showing
46 changed files
with
3,517 additions
and
922 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
Copyright 2021 The Scribe authors. | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Affero General Public License as published | ||
by the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License | ||
along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package mover | ||
|
||
import ( | ||
"github.com/go-logr/logr" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
|
||
scribev1alpha1 "github.com/backube/scribe/api/v1alpha1" | ||
) | ||
|
||
// Catalog is the list of the available Builders for the controller to use when | ||
// attempting to find an appropriate mover to service the RS/RD CR. | ||
var Catalog []Builder | ||
|
||
// Register should be called by each mover via an init function to register the | ||
// mover w/ the main Scribe codebase. | ||
func Register(builder Builder) { | ||
Catalog = append(Catalog, builder) | ||
} | ||
|
||
// Builder is used to construct Mover instances for the different data | ||
// mover types. | ||
type Builder interface { | ||
// FromSource attempts to construct a Mover from the provided | ||
// ReplicationSource. If the RS does not reference the Builder's mover type, | ||
// this function should return (nil, nil). | ||
FromSource(client client.Client, logger logr.Logger, | ||
source *scribev1alpha1.ReplicationSource) (Mover, error) | ||
|
||
// FromDestination attempts to construct a Mover from the provided | ||
// ReplicationDestination. If the RS does not reference the Builder's mover | ||
// type, this function should return (nil, nil). | ||
FromDestination(client client.Client, logger logr.Logger, | ||
destination *scribev1alpha1.ReplicationDestination) (Mover, error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
Copyright 2021 The Scribe authors. | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Affero General Public License as published | ||
by the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License | ||
along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
// Scribe data movers are created by implementing the interfaces in this | ||
// package. Each data mover must implement the Builder interface that constructs | ||
// instances of the Mover (interface) given a ReplicationSource or | ||
// ReplicationDestination CR. These builders must be created and Register()-ed | ||
// with the Catalog at startup time for that mover type to be available. | ||
// | ||
// When an RS or RD CR is reconciled, the Builders in the Catalog are tried in | ||
// sequence. If one successfully returns a Mover, that mover is used to perform | ||
// the reconcile. | ||
// | ||
// Movers implement the actual synchronization of data and return a Result from | ||
// each invocation. When one of the Mover's functions returns Completed(), the | ||
// operation (either synchronization or cleanup of a previous synchronization is | ||
// considered to be completed). | ||
package mover |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
Copyright 2021 The Scribe authors. | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Affero General Public License as published | ||
by the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License | ||
along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package mover | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
v1 "k8s.io/api/core/v1" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
) | ||
|
||
// Mover is a common interface that all data movers implement | ||
type Mover interface { | ||
// The name of this data mover | ||
Name() string | ||
|
||
// Synchronize begins or continues a synchronization attempt. Attempts will | ||
// continue at least until the Result indicates that the synchronization is | ||
// complete. Must be idempotent. | ||
Synchronize(ctx context.Context) (Result, error) | ||
|
||
// Cleanup begins or continues the post-synchronization cleanup of temporary | ||
// resources. Must be idempotent. | ||
Cleanup(ctx context.Context) (Result, error) | ||
} | ||
|
||
// Result indicates the outcome of a synchronization attempt | ||
type Result struct { | ||
// Completed is set to true if the synchronization has completed. RetryAfter | ||
// will be ignored. | ||
Completed bool | ||
|
||
// Image is the resulting data image (PVC or Snapshot) that has been created | ||
// by the Synchronize() operation. | ||
Image *v1.TypedLocalObjectReference | ||
|
||
// RetryAfter is used to indicate whether synchronization should be | ||
// explicitly retried, and when. Setting to nil (default) does not cause an | ||
// explicit retry, but Synchronize() will be retried when a watched object | ||
// is modified. Setting to 0 indicates an immediate retry. Other values | ||
// provide a delay. | ||
RetryAfter *time.Duration | ||
} | ||
|
||
// ReconcileResult converts a Result into controllerruntime's reconcile result | ||
// structure | ||
func (mr Result) ReconcileResult() ctrl.Result { | ||
if mr.RetryAfter != nil { | ||
return ctrl.Result{ | ||
Requeue: true, | ||
RequeueAfter: *mr.RetryAfter, | ||
} | ||
} | ||
return ctrl.Result{} | ||
} | ||
|
||
// InProgress result indicates that the requested operation is still ongoing, | ||
// but it does not request an explicit requeueing. | ||
func InProgress() Result { return Result{} } | ||
|
||
// RetryAfter indicates the operation is ongoing and requests explicit | ||
// requeueing after the provided duration. | ||
func RetryAfter(s time.Duration) Result { return Result{RetryAfter: &s} } | ||
|
||
// Complete indicates that the operation has completed. | ||
func Complete() Result { return Result{Completed: true} } | ||
|
||
// CompleteWithImage indicates that the operation has completed, and it provides | ||
// the synchronized image to the controller. | ||
func CompleteWithImage(image *v1.TypedLocalObjectReference) Result { | ||
return Result{ | ||
Completed: true, | ||
Image: image, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/* | ||
Copyright 2021 The Scribe authors. | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU Affero General Public License as published | ||
by the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU Affero General Public License for more details. | ||
You should have received a copy of the GNU Affero General Public License | ||
along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package restic | ||
|
||
import ( | ||
"flag" | ||
|
||
"github.com/go-logr/logr" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
|
||
scribev1alpha1 "github.com/backube/scribe/api/v1alpha1" | ||
"github.com/backube/scribe/controllers/mover" | ||
"github.com/backube/scribe/controllers/volumehandler" | ||
) | ||
|
||
// defaultResticContainerImage is the default container image for the restic | ||
// data mover | ||
const defaultResticContainerImage = "quay.io/backube/scribe-mover-restic:latest" | ||
|
||
// resticContainerImage is the container image name of the restic data mover | ||
var resticContainerImage string | ||
|
||
type Builder struct{} | ||
|
||
var _ mover.Builder = &Builder{} | ||
|
||
func Register() { | ||
flag.StringVar(&resticContainerImage, "restic-container-image", | ||
defaultResticContainerImage, "The container image for the restic data mover") | ||
mover.Register(&Builder{}) | ||
} | ||
|
||
func (rb *Builder) FromSource(client client.Client, logger logr.Logger, | ||
source *scribev1alpha1.ReplicationSource) (mover.Mover, error) { | ||
// Only build if the CR belongs to us | ||
if source.Spec.Restic == nil { | ||
return nil, nil | ||
} | ||
|
||
// Create ReplicationSourceResticStatus to write restic status | ||
if source.Status.Restic == nil { | ||
source.Status.Restic = &scribev1alpha1.ReplicationSourceResticStatus{} | ||
} | ||
|
||
vh, err := volumehandler.NewVolumeHandler( | ||
volumehandler.WithClient(client), | ||
volumehandler.WithOwner(source), | ||
volumehandler.FromSource(&source.Spec.Restic.ReplicationSourceVolumeOptions), | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &Mover{ | ||
client: client, | ||
logger: logger.WithValues("method", "Restic"), | ||
owner: source, | ||
vh: vh, | ||
cacheAccessModes: source.Spec.Restic.CacheAccessModes, | ||
cacheCapacity: source.Spec.Restic.CacheCapacity, | ||
cacheStorageClassName: source.Spec.Restic.CacheStorageClassName, | ||
repositoryName: source.Spec.Restic.Repository, | ||
isSource: true, | ||
paused: source.Spec.Paused, | ||
mainPVCName: &source.Spec.SourcePVC, | ||
pruneInterval: source.Spec.Restic.PruneIntervalDays, | ||
retainPolicy: source.Spec.Restic.Retain, | ||
sourceStatus: source.Status.Restic, | ||
}, nil | ||
} | ||
|
||
func (rb *Builder) FromDestination(client client.Client, logger logr.Logger, | ||
destination *scribev1alpha1.ReplicationDestination) (mover.Mover, error) { | ||
// Only build if the CR belongs to us | ||
if destination.Spec.Restic == nil { | ||
return nil, nil | ||
} | ||
|
||
vh, err := volumehandler.NewVolumeHandler( | ||
volumehandler.WithClient(client), | ||
volumehandler.WithOwner(destination), | ||
volumehandler.FromDestination(&destination.Spec.Restic.ReplicationDestinationVolumeOptions), | ||
) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &Mover{ | ||
client: client, | ||
logger: logger.WithValues("method", "Restic"), | ||
owner: destination, | ||
vh: vh, | ||
cacheAccessModes: destination.Spec.Restic.CacheAccessModes, | ||
cacheCapacity: destination.Spec.Restic.CacheCapacity, | ||
cacheStorageClassName: destination.Spec.Restic.CacheStorageClassName, | ||
repositoryName: destination.Spec.Restic.Repository, | ||
isSource: false, | ||
paused: destination.Spec.Paused, | ||
mainPVCName: destination.Spec.Restic.DestinationPVC, | ||
}, nil | ||
} |
Oops, something went wrong.