Remove Reference of itemsnapshotter (#5997)

It will be removed as we choose to use BIAv2 for progress monitoring.

Signed-off-by: Daniel Jiang <jiangd@vmware.com>
This commit is contained in:
Daniel Jiang
2023-03-21 09:05:29 +08:00
committed by GitHub
parent 2c26c1d5fe
commit 458560795b
25 changed files with 10 additions and 3212 deletions
+1
View File
@@ -0,0 +1 @@
Remove Reference of itemsnapshotter
+2 -13
View File
@@ -67,9 +67,7 @@ type Backupper interface {
// Backup takes a backup using the specification in the velerov1api.Backup and writes backup and log data
// to the given writers.
Backup(logger logrus.FieldLogger, backup *Request, backupFile io.Writer, actions []biav2.BackupItemAction, volumeSnapshotterGetter VolumeSnapshotterGetter) error
BackupWithResolvers(log logrus.FieldLogger, backupRequest *Request, backupFile io.Writer,
backupItemActionResolver framework.BackupItemActionResolverV2, itemSnapshotterResolver framework.ItemSnapshotterResolver,
volumeSnapshotterGetter VolumeSnapshotterGetter) error
BackupWithResolvers(log logrus.FieldLogger, backupRequest *Request, backupFile io.Writer, backupItemActionResolver framework.BackupItemActionResolverV2, volumeSnapshotterGetter VolumeSnapshotterGetter) error
FinalizeBackup(log logrus.FieldLogger, backupRequest *Request, inBackupFile io.Reader, outBackupFile io.Writer,
backupItemActionResolver framework.BackupItemActionResolverV2,
asyncBIAOperations []*itemoperation.BackupOperation) error
@@ -182,16 +180,13 @@ type VolumeSnapshotterGetter interface {
func (kb *kubernetesBackupper) Backup(log logrus.FieldLogger, backupRequest *Request, backupFile io.Writer,
actions []biav2.BackupItemAction, volumeSnapshotterGetter VolumeSnapshotterGetter) error {
backupItemActions := framework.NewBackupItemActionResolverV2(actions)
itemSnapshotters := framework.NewItemSnapshotterResolver(nil)
return kb.BackupWithResolvers(log, backupRequest, backupFile, backupItemActions, itemSnapshotters,
volumeSnapshotterGetter)
return kb.BackupWithResolvers(log, backupRequest, backupFile, backupItemActions, volumeSnapshotterGetter)
}
func (kb *kubernetesBackupper) BackupWithResolvers(log logrus.FieldLogger,
backupRequest *Request,
backupFile io.Writer,
backupItemActionResolver framework.BackupItemActionResolverV2,
itemSnapshotterResolver framework.ItemSnapshotterResolver,
volumeSnapshotterGetter VolumeSnapshotterGetter) error {
gzippedData := gzip.NewWriter(backupFile)
defer gzippedData.Close()
@@ -239,12 +234,6 @@ func (kb *kubernetesBackupper) BackupWithResolvers(log logrus.FieldLogger,
return err
}
backupRequest.ResolvedItemSnapshotters, err = itemSnapshotterResolver.ResolveActions(kb.discoveryHelper, log)
if err != nil {
log.WithError(errors.WithStack(err)).Debugf("Error from itemSnapshotterResolver.ResolveActions")
return err
}
backupRequest.BackedUpItems = map[itemKey]struct{}{}
podVolumeTimeout := kb.podVolumeTimeout
-1
View File
@@ -47,7 +47,6 @@ type Request struct {
ResourceIncludesExcludes collections.IncludesExcludesInterface
ResourceHooks []hook.ResourceHook
ResolvedActions []framework.BackupItemResolvedActionV2
ResolvedItemSnapshotters []framework.ItemSnapshotterResolvedAction
VolumeSnapshots []*volume.Snapshot
PodVolumeBackups []*velerov1api.PodVolumeBackup
BackedUpItems map[itemKey]struct{}
+1 -8
View File
@@ -611,11 +611,6 @@ func (b *backupReconciler) runBackup(backup *pkgbackup.Request) error {
if err != nil {
return err
}
itemSnapshotters, err := pluginManager.GetItemSnapshotters()
if err != nil {
return err
}
backupLog.Info("Setting up backup store to check for backup existence")
backupStore, err := b.backupStoreGetter.Get(backup.StorageLocation, pluginManager, backupLog)
if err != nil {
@@ -633,11 +628,9 @@ func (b *backupReconciler) runBackup(backup *pkgbackup.Request) error {
}
backupItemActionsResolver := framework.NewBackupItemActionResolverV2(actions)
itemSnapshottersResolver := framework.NewItemSnapshotterResolver(itemSnapshotters)
var fatalErrs []error
if err := b.backupper.BackupWithResolvers(backupLog, backup, backupFile, backupItemActionsResolver,
itemSnapshottersResolver, pluginManager); err != nil {
if err := b.backupper.BackupWithResolvers(backupLog, backup, backupFile, backupItemActionsResolver, pluginManager); err != nil {
fatalErrs = append(fatalErrs, err)
}
+3 -5
View File
@@ -70,9 +70,8 @@ func (b *fakeBackupper) Backup(logger logrus.FieldLogger, backup *pkgbackup.Requ
}
func (b *fakeBackupper) BackupWithResolvers(logger logrus.FieldLogger, backup *pkgbackup.Request, backupFile io.Writer,
backupItemActionResolver framework.BackupItemActionResolverV2, itemSnapshotterResolver framework.ItemSnapshotterResolver,
volumeSnapshotterGetter pkgbackup.VolumeSnapshotterGetter) error {
args := b.Called(logger, backup, backupFile, backupItemActionResolver, itemSnapshotterResolver, volumeSnapshotterGetter)
backupItemActionResolver framework.BackupItemActionResolverV2, volumeSnapshotterGetter pkgbackup.VolumeSnapshotterGetter) error {
args := b.Called(logger, backup, backupFile, backupItemActionResolver, volumeSnapshotterGetter)
return args.Error(0)
}
@@ -1047,9 +1046,8 @@ func TestProcessBackupCompletions(t *testing.T) {
pluginManager.On("GetBackupItemActionsV2").Return(nil, nil)
pluginManager.On("CleanupClients").Return(nil)
pluginManager.On("GetItemSnapshotters").Return(nil, nil)
backupper.On("Backup", mock.Anything, mock.Anything, mock.Anything, []biav2.BackupItemAction(nil), pluginManager).Return(nil)
backupper.On("BackupWithResolvers", mock.Anything, mock.Anything, mock.Anything, framework.BackupItemActionResolverV2{}, framework.ItemSnapshotterResolver{}, pluginManager).Return(nil)
backupper.On("BackupWithResolvers", mock.Anything, mock.Anything, mock.Anything, framework.BackupItemActionResolverV2{}, pluginManager).Return(nil)
backupStore.On("BackupExists", test.backupLocation.Spec.StorageType.ObjectStorage.Bucket, test.backup.Name).Return(test.backupExists, test.existenceCheckError)
// Ensure we have a CompletionTimestamp when uploading and that the backup name matches the backup in the object store.
+1 -8
View File
@@ -431,12 +431,6 @@ func (r *restoreReconciler) runValidatedRestore(restore *api.Restore, info backu
}
actionsResolver := framework.NewRestoreItemActionResolverV2(actions)
itemSnapshotters, err := pluginManager.GetItemSnapshotters()
if err != nil {
return errors.Wrap(err, "error getting item snapshotters")
}
snapshotItemResolver := framework.NewItemSnapshotterResolver(itemSnapshotters)
backupFile, err := downloadToTempFile(restore.Spec.BackupName, backupStore, restoreLog)
if err != nil {
return errors.Wrap(err, "error downloading backup")
@@ -475,8 +469,7 @@ func (r *restoreReconciler) runValidatedRestore(restore *api.Restore, info backu
VolumeSnapshots: volumeSnapshots,
BackupReader: backupFile,
}
restoreWarnings, restoreErrors := r.restorer.RestoreWithResolvers(restoreReq, actionsResolver, snapshotItemResolver,
pluginManager)
restoreWarnings, restoreErrors := r.restorer.RestoreWithResolvers(restoreReq, actionsResolver, pluginManager)
// Iterate over restore item operations and update progress.
// Any errors on operations at this point should be added to restore errors.
+1 -4
View File
@@ -41,7 +41,6 @@ import (
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt"
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
pluginmocks "github.com/vmware-tanzu/velero/pkg/plugin/mocks"
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
riav2 "github.com/vmware-tanzu/velero/pkg/plugin/velero/restoreitemaction/v2"
pkgrestore "github.com/vmware-tanzu/velero/pkg/restore"
velerotest "github.com/vmware-tanzu/velero/pkg/test"
@@ -481,7 +480,6 @@ func TestRestoreReconcile(t *testing.T) {
if test.restore != nil {
pluginManager.On("GetRestoreItemActionsV2").Return(nil, nil)
pluginManager.On("GetItemSnapshotters").Return([]isv1.ItemSnapshotter{}, nil)
pluginManager.On("CleanupClients")
}
@@ -786,10 +784,9 @@ func (r *fakeRestorer) Restore(
func (r *fakeRestorer) RestoreWithResolvers(req *pkgrestore.Request,
resolver framework.RestoreItemActionResolverV2,
itemSnapshotterResolver framework.ItemSnapshotterResolver,
volumeSnapshotterGetter pkgrestore.VolumeSnapshotterGetter,
) (results.Result, results.Result) {
res := r.Called(req.Log, req.Restore, req.Backup, req.BackupReader, resolver, itemSnapshotterResolver,
res := r.Called(req.Log, req.Restore, req.Backup, req.BackupReader, resolver,
r.kbClient, volumeSnapshotterGetter)
r.calledWithArg = *req.Restore
-38
View File
@@ -34,7 +34,6 @@ import (
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
biav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v1"
biav2 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v2"
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
riav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/restoreitemaction/v1"
riav2 "github.com/vmware-tanzu/velero/pkg/plugin/velero/restoreitemaction/v2"
vsv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/volumesnapshotter/v1"
@@ -78,12 +77,6 @@ type Manager interface {
// GetDeleteItemAction returns the delete item action plugin for name.
GetDeleteItemAction(name string) (velero.DeleteItemAction, error)
// GetItemSnapshotter returns the item snapshotter plugin for name
GetItemSnapshotter(name string) (isv1.ItemSnapshotter, error)
// GetItemSnapshotters returns all item snapshotter plugins
GetItemSnapshotters() ([]isv1.ItemSnapshotter, error)
// CleanupClients terminates all of the Manager's running plugin processes.
CleanupClients()
}
@@ -381,37 +374,6 @@ func (m *manager) GetDeleteItemAction(name string) (velero.DeleteItemAction, err
return r, nil
}
func (m *manager) GetItemSnapshotter(name string) (isv1.ItemSnapshotter, error) {
name = sanitizeName(name)
restartableProcess, err := m.getRestartableProcess(common.PluginKindItemSnapshotter, name)
if err != nil {
return nil, err
}
r := NewRestartableItemSnapshotter(name, restartableProcess)
return r, nil
}
func (m *manager) GetItemSnapshotters() ([]isv1.ItemSnapshotter, error) {
list := m.registry.List(common.PluginKindItemSnapshotter)
actions := make([]isv1.ItemSnapshotter, 0, len(list))
for i := range list {
id := list[i]
r, err := m.GetItemSnapshotter(id.Name)
if err != nil {
return nil, err
}
actions = append(actions, r)
}
return actions, nil
}
// sanitizeName adds "velero.io" to legacy plugins that weren't namespaced.
func sanitizeName(name string) string {
// Backwards compatibility with non-namespaced Velero plugins, following principle of least surprise
@@ -78,7 +78,6 @@ func (b *clientBuilder) clientConfig() *hcplugin.ClientConfig {
string(common.PluginKindRestoreItemAction): framework.NewRestoreItemActionPlugin(common.ClientLogger(b.clientLogger)),
string(common.PluginKindRestoreItemActionV2): riav2.NewRestoreItemActionPlugin(common.ClientLogger(b.clientLogger)),
string(common.PluginKindDeleteItemAction): framework.NewDeleteItemActionPlugin(common.ClientLogger(b.clientLogger)),
string(common.PluginKindItemSnapshotter): framework.NewItemSnapshotterPlugin(common.ClientLogger(b.clientLogger)),
},
Logger: b.pluginLogger,
Cmd: exec.Command(b.commandName, b.commandArgs...), //nolint
@@ -71,7 +71,6 @@ func TestClientConfig(t *testing.T) {
string(common.PluginKindRestoreItemAction): framework.NewRestoreItemActionPlugin(common.ClientLogger(logger)),
string(common.PluginKindRestoreItemActionV2): riav2.NewRestoreItemActionPlugin(common.ClientLogger(logger)),
string(common.PluginKindDeleteItemAction): framework.NewDeleteItemActionPlugin(common.ClientLogger(logger)),
string(common.PluginKindItemSnapshotter): framework.NewItemSnapshotterPlugin(common.ClientLogger(logger)),
},
Logger: cb.pluginLogger,
Cmd: exec.Command(cb.commandName, cb.commandArgs...),
@@ -1,131 +0,0 @@
/*
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package clientmgmt
import (
"context"
"github.com/pkg/errors"
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
)
type restartableItemSnapshotter struct {
key process.KindAndName
sharedPluginProcess process.RestartableProcess
}
// NewRestartableItemSnapshotter returns a new restartableItemSnapshotter.
func NewRestartableItemSnapshotter(name string, sharedPluginProcess process.RestartableProcess) *restartableItemSnapshotter {
r := &restartableItemSnapshotter{
key: process.KindAndName{Kind: common.PluginKindItemSnapshotter, Name: name},
sharedPluginProcess: sharedPluginProcess,
}
return r
}
// getItemSnapshotter returns the item snapshotter for this restartableItemSnapshotter. It does *not* restart the
// plugin process.
func (r *restartableItemSnapshotter) getItemSnapshotter() (isv1.ItemSnapshotter, error) {
plugin, err := r.sharedPluginProcess.GetByKindAndName(r.key)
if err != nil {
return nil, err
}
itemSnapshotter, ok := plugin.(isv1.ItemSnapshotter)
if !ok {
return nil, errors.Errorf("%T is not an ItemSnapshotter!", plugin)
}
return itemSnapshotter, nil
}
// getDelegate restarts the plugin process (if needed) and returns the item snapshotter for this restartableItemSnapshotter.
func (r *restartableItemSnapshotter) getDelegate() (isv1.ItemSnapshotter, error) {
if err := r.sharedPluginProcess.ResetIfNeeded(); err != nil {
return nil, err
}
return r.getItemSnapshotter()
}
func (r *restartableItemSnapshotter) Init(config map[string]string) error {
delegate, err := r.getDelegate()
if err != nil {
return err
}
return delegate.Init(config)
}
// AppliesTo restarts the plugin's process if needed, then delegates the call.
func (r *restartableItemSnapshotter) AppliesTo() (velero.ResourceSelector, error) {
delegate, err := r.getDelegate()
if err != nil {
return velero.ResourceSelector{}, err
}
return delegate.AppliesTo()
}
func (r *restartableItemSnapshotter) AlsoHandles(input *isv1.AlsoHandlesInput) ([]velero.ResourceIdentifier, error) {
delegate, err := r.getDelegate()
if err != nil {
return nil, err
}
return delegate.AlsoHandles(input)
}
func (r *restartableItemSnapshotter) SnapshotItem(ctx context.Context, input *isv1.SnapshotItemInput) (*isv1.SnapshotItemOutput, error) {
delegate, err := r.getDelegate()
if err != nil {
return nil, err
}
return delegate.SnapshotItem(ctx, input)
}
func (r *restartableItemSnapshotter) Progress(input *isv1.ProgressInput) (*isv1.ProgressOutput, error) {
delegate, err := r.getDelegate()
if err != nil {
return nil, err
}
return delegate.Progress(input)
}
func (r *restartableItemSnapshotter) DeleteSnapshot(ctx context.Context, input *isv1.DeleteSnapshotInput) error {
delegate, err := r.getDelegate()
if err != nil {
return err
}
return delegate.DeleteSnapshot(ctx, input)
}
func (r *restartableItemSnapshotter) CreateItemFromSnapshot(ctx context.Context, input *isv1.CreateItemInput) (*isv1.CreateItemOutput, error) {
delegate, err := r.getDelegate()
if err != nil {
return nil, err
}
return delegate.CreateItemFromSnapshot(ctx, input)
}
@@ -1,234 +0,0 @@
/*
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package clientmgmt
import (
"context"
"testing"
"time"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/vmware-tanzu/velero/internal/restartabletest"
v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1/mocks"
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
)
func TestRestartableGetItemSnapshotter(t *testing.T) {
tests := []struct {
name string
plugin interface{}
getError error
expectedError string
}{
{
name: "error getting by kind and name",
getError: errors.Errorf("get error"),
expectedError: "get error",
},
{
name: "wrong type",
plugin: 3,
expectedError: "int is not an ItemSnapshotter!",
},
{
name: "happy path",
plugin: new(mocks.ItemSnapshotter),
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
p := new(restartabletest.MockRestartableProcess)
defer p.AssertExpectations(t)
name := "pvc"
key := process.KindAndName{Kind: common.PluginKindItemSnapshotter, Name: name}
p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError)
r := NewRestartableItemSnapshotter(name, p)
a, err := r.getItemSnapshotter()
if tc.expectedError != "" {
assert.EqualError(t, err, tc.expectedError)
return
}
require.NoError(t, err)
assert.Equal(t, tc.plugin, a)
})
}
}
func TestRestartableItemSnapshotterGetDelegate(t *testing.T) {
p := new(restartabletest.MockRestartableProcess)
defer p.AssertExpectations(t)
// Reset error
p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once()
name := "pvc"
r := NewRestartableItemSnapshotter(name, p)
a, err := r.getDelegate()
assert.Nil(t, a)
assert.EqualError(t, err, "reset error")
// Happy path
p.On("ResetIfNeeded").Return(nil)
expected := new(mocks.ItemSnapshotter)
key := process.KindAndName{Kind: common.PluginKindItemSnapshotter, Name: name}
p.On("GetByKindAndName", key).Return(expected, nil)
a, err = r.getDelegate()
assert.NoError(t, err)
assert.Equal(t, expected, a)
}
func TestRestartableItemSnasphotterDelegatedFunctions(t *testing.T) {
b := new(v1.Backup)
pv := &unstructured.Unstructured{
Object: map[string]interface{}{
"color": "blue",
},
}
sii := &isv1.SnapshotItemInput{
Item: pv,
Params: nil,
Backup: b,
}
ctx := context.Background()
pvToReturn := &unstructured.Unstructured{
Object: map[string]interface{}{
"color": "green",
},
}
additionalItems := []velero.ResourceIdentifier{
{
GroupResource: schema.GroupResource{Group: "velero.io", Resource: "backups"},
},
}
sio := &isv1.SnapshotItemOutput{
UpdatedItem: pvToReturn,
SnapshotID: "",
SnapshotMetadata: nil,
AdditionalItems: additionalItems,
HandledItems: nil,
}
cii := &isv1.CreateItemInput{
SnapshottedItem: nil,
SnapshotID: "",
ItemFromBackup: nil,
SnapshotMetadata: nil,
Params: nil,
Restore: nil,
}
cio := &isv1.CreateItemOutput{
UpdatedItem: nil,
AdditionalItems: nil,
SkipRestore: false,
}
pi := &isv1.ProgressInput{
ItemID: velero.ResourceIdentifier{},
SnapshotID: "",
Backup: nil,
}
po := &isv1.ProgressOutput{
Phase: isv1.SnapshotPhaseInProgress,
Err: "",
ItemsCompleted: 0,
ItemsToComplete: 0,
Started: time.Time{},
Updated: time.Time{},
}
dsi := &isv1.DeleteSnapshotInput{
SnapshotID: "",
ItemFromBackup: nil,
SnapshotMetadata: nil,
Params: nil,
}
restartabletest.RunRestartableDelegateTests(
t,
common.PluginKindItemSnapshotter,
func(key process.KindAndName, p process.RestartableProcess) interface{} {
return &restartableItemSnapshotter{
key: key,
sharedPluginProcess: p,
}
},
func() restartabletest.Mockable {
return new(mocks.ItemSnapshotter)
},
restartabletest.RestartableDelegateTest{
Function: "Init",
Inputs: []interface{}{map[string]string{}},
ExpectedErrorOutputs: []interface{}{errors.Errorf("reset error")},
ExpectedDelegateOutputs: []interface{}{errors.Errorf("delegate error")},
},
restartabletest.RestartableDelegateTest{
Function: "AppliesTo",
Inputs: []interface{}{},
ExpectedErrorOutputs: []interface{}{velero.ResourceSelector{}, errors.Errorf("reset error")},
ExpectedDelegateOutputs: []interface{}{velero.ResourceSelector{IncludedNamespaces: []string{"a"}}, errors.Errorf("delegate error")},
},
restartabletest.RestartableDelegateTest{
Function: "AlsoHandles",
Inputs: []interface{}{&isv1.AlsoHandlesInput{}},
ExpectedErrorOutputs: []interface{}{[]velero.ResourceIdentifier(nil), errors.Errorf("reset error")},
ExpectedDelegateOutputs: []interface{}{[]velero.ResourceIdentifier(nil), errors.Errorf("delegate error")},
},
restartabletest.RestartableDelegateTest{
Function: "SnapshotItem",
Inputs: []interface{}{ctx, sii},
ExpectedErrorOutputs: []interface{}{nil, errors.Errorf("reset error")},
ExpectedDelegateOutputs: []interface{}{sio, errors.Errorf("delegate error")},
},
restartabletest.RestartableDelegateTest{
Function: "CreateItemFromSnapshot",
Inputs: []interface{}{ctx, cii},
ExpectedErrorOutputs: []interface{}{nil, errors.Errorf("reset error")},
ExpectedDelegateOutputs: []interface{}{cio, errors.Errorf("delegate error")},
},
restartabletest.RestartableDelegateTest{
Function: "Progress",
Inputs: []interface{}{pi},
ExpectedErrorOutputs: []interface{}{nil, errors.Errorf("reset error")},
ExpectedDelegateOutputs: []interface{}{po, errors.Errorf("delegate error")},
},
restartabletest.RestartableDelegateTest{
Function: "DeleteSnapshot",
Inputs: []interface{}{ctx, dsi},
ExpectedErrorOutputs: []interface{}{errors.Errorf("reset error")},
ExpectedDelegateOutputs: []interface{}{errors.Errorf("delegate error")},
},
)
}
-36
View File
@@ -27,7 +27,6 @@ import (
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
biav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v1"
biav2 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v2"
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
riav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/restoreitemaction/v1"
riav2 "github.com/vmware-tanzu/velero/pkg/plugin/velero/restoreitemaction/v2"
"github.com/vmware-tanzu/velero/pkg/util/collections"
@@ -141,12 +140,6 @@ func NewDeleteItemActionResolver(actions []velero.DeleteItemAction) DeleteItemAc
}
}
func NewItemSnapshotterResolver(actions []isv1.ItemSnapshotter) ItemSnapshotterResolver {
return ItemSnapshotterResolver{
actions: actions,
}
}
type ActionResolver interface {
ResolveAction(helper discovery.Helper, action velero.Applicable, log logrus.FieldLogger) (ResolvedAction, error)
}
@@ -287,32 +280,3 @@ func (recv DeleteItemActionResolver) ResolveActions(helper discovery.Helper, log
}
return resolved, nil
}
type ItemSnapshotterResolvedAction struct {
isv1.ItemSnapshotter
resolvedAction
}
type ItemSnapshotterResolver struct {
actions []isv1.ItemSnapshotter
}
func (recv ItemSnapshotterResolver) ResolveActions(helper discovery.Helper, log logrus.FieldLogger) ([]ItemSnapshotterResolvedAction, error) {
var resolved []ItemSnapshotterResolvedAction
for _, action := range recv.actions {
resources, namespaces, selector, err := resolveAction(helper, action)
if err != nil {
return nil, err
}
res := ItemSnapshotterResolvedAction{
ItemSnapshotter: action,
resolvedAction: resolvedAction{
ResourceIncludesExcludes: resources,
NamespaceIncludesExcludes: namespaces,
Selector: selector,
},
}
resolved = append(resolved, res)
}
return resolved, nil
}
@@ -47,9 +47,6 @@ const (
// PluginKindDeleteItemAction represents a delete item action plugin.
PluginKindDeleteItemAction PluginKind = "DeleteItemAction"
// PluginKindItemSnapshotter represents an item snapshotter plugin
PluginKindItemSnapshotter PluginKind = "ItemSnapshotter"
// PluginKindPluginLister represents a plugin lister plugin.
PluginKindPluginLister PluginKind = "PluginLister"
)
@@ -73,6 +70,5 @@ func AllPluginKinds() map[string]PluginKind {
allPluginKinds[PluginKindRestoreItemAction.String()] = PluginKindRestoreItemAction
allPluginKinds[PluginKindRestoreItemActionV2.String()] = PluginKindRestoreItemActionV2
allPluginKinds[PluginKindDeleteItemAction.String()] = PluginKindDeleteItemAction
allPluginKinds[PluginKindItemSnapshotter.String()] = PluginKindItemSnapshotter
return allPluginKinds
}
-45
View File
@@ -1,45 +0,0 @@
/*
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package framework
import (
plugin "github.com/hashicorp/go-plugin"
"golang.org/x/net/context"
"google.golang.org/grpc"
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
proto "github.com/vmware-tanzu/velero/pkg/plugin/generated"
)
// ItemSnapshotterPlugin is an implementation of go-plugin's Plugin
// interface with support for gRPC for the ItemSnapshotter
// interface.
type ItemSnapshotterPlugin struct {
plugin.NetRPCUnsupportedPlugin
*common.PluginBase
}
// GRPCClient returns a clientDispenser for ItemSnapshotter gRPC clients.
func (p *ItemSnapshotterPlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, clientConn *grpc.ClientConn) (interface{}, error) {
return common.NewClientDispenser(p.ClientLogger, clientConn, newItemSnapshotterGRPCClient), nil
}
// GRPCServer registers an ItemSnapshotter gRPC server.
func (p *ItemSnapshotterPlugin) GRPCServer(_ *plugin.GRPCBroker, server *grpc.Server) error {
proto.RegisterItemSnapshotterServer(server, &ItemSnapshotterGRPCServer{mux: p.ServerMux})
return nil
}
@@ -1,240 +0,0 @@
/*
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package framework
import (
"context"
"encoding/json"
"time"
"github.com/pkg/errors"
"google.golang.org/grpc"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
proto "github.com/vmware-tanzu/velero/pkg/plugin/generated"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
)
// NewItemSnapshotterPlugin constructs a ItemSnapshotterPlugin.
func NewItemSnapshotterPlugin(options ...common.PluginOption) *ItemSnapshotterPlugin {
return &ItemSnapshotterPlugin{
PluginBase: common.NewPluginBase(options...),
}
}
func newItemSnapshotterGRPCClient(base *common.ClientBase, clientConn *grpc.ClientConn) interface{} {
return &ItemSnapshotterGRPCClient{
ClientBase: base,
grpcClient: proto.NewItemSnapshotterClient(clientConn),
}
}
// ItemSnapshotterGRPCClient implements the ItemSnapshotter interface and uses a
// gRPC client to make calls to the plugin server.
type ItemSnapshotterGRPCClient struct {
*common.ClientBase
grpcClient proto.ItemSnapshotterClient
}
func (recv ItemSnapshotterGRPCClient) Init(config map[string]string) error {
req := &proto.ItemSnapshotterInitRequest{
Plugin: recv.Plugin,
Config: config,
}
_, err := recv.grpcClient.Init(context.Background(), req)
return err
}
func (recv ItemSnapshotterGRPCClient) AppliesTo() (velero.ResourceSelector, error) {
req := &proto.ItemSnapshotterAppliesToRequest{
Plugin: recv.Plugin,
}
res, err := recv.grpcClient.AppliesTo(context.Background(), req)
if err != nil {
return velero.ResourceSelector{}, common.FromGRPCError(err)
}
if res.ResourceSelector == nil {
return velero.ResourceSelector{}, nil
}
return velero.ResourceSelector{
IncludedNamespaces: res.ResourceSelector.IncludedNamespaces,
ExcludedNamespaces: res.ResourceSelector.ExcludedNamespaces,
IncludedResources: res.ResourceSelector.IncludedResources,
ExcludedResources: res.ResourceSelector.ExcludedResources,
LabelSelector: res.ResourceSelector.Selector,
}, nil
}
func (recv ItemSnapshotterGRPCClient) AlsoHandles(input *isv1.AlsoHandlesInput) ([]velero.ResourceIdentifier, error) {
itemJSON, err := json.Marshal(input.Item.UnstructuredContent())
if err != nil {
return nil, errors.WithStack(err)
}
backupJSON, err := json.Marshal(input.Backup)
if err != nil {
return nil, errors.WithStack(err)
}
req := &proto.AlsoHandlesRequest{
Plugin: recv.Plugin,
Item: itemJSON,
Backup: backupJSON,
}
res, err := recv.grpcClient.AlsoHandles(context.Background(), req)
if err != nil {
return nil, errors.WithStack(err)
}
handledItems := unpackResourceIdentifiers(res.HandledItems)
return handledItems, nil
}
func (recv ItemSnapshotterGRPCClient) SnapshotItem(ctx context.Context, input *isv1.SnapshotItemInput) (*isv1.SnapshotItemOutput, error) {
itemJSON, err := json.Marshal(input.Item.UnstructuredContent())
if err != nil {
return nil, errors.WithStack(err)
}
backupJSON, err := json.Marshal(input.Backup)
if err != nil {
return nil, errors.WithStack(err)
}
req := &proto.SnapshotItemRequest{
Plugin: recv.Plugin,
Item: itemJSON,
Backup: backupJSON,
}
res, err := recv.grpcClient.SnapshotItem(ctx, req)
if err != nil {
return nil, errors.WithStack(err)
}
var updatedItem unstructured.Unstructured
if err := json.Unmarshal(res.Item, &updatedItem); err != nil {
return nil, errors.WithStack(err)
}
additionalItems := unpackResourceIdentifiers(res.AdditionalItems)
handledItems := unpackResourceIdentifiers(res.HandledItems)
sio := isv1.SnapshotItemOutput{
UpdatedItem: &updatedItem,
SnapshotID: res.SnapshotID,
SnapshotMetadata: res.SnapshotMetadata,
AdditionalItems: additionalItems,
HandledItems: handledItems,
}
return &sio, nil
}
func (recv ItemSnapshotterGRPCClient) Progress(input *isv1.ProgressInput) (*isv1.ProgressOutput, error) {
backupJSON, err := json.Marshal(input.Backup)
if err != nil {
return nil, errors.WithStack(err)
}
req := &proto.ProgressRequest{
Plugin: recv.Plugin,
ItemID: resourceIdentifierToProto(input.ItemID),
SnapshotID: input.SnapshotID,
Backup: backupJSON,
}
res, err := recv.grpcClient.Progress(context.Background(), req)
if err != nil {
return nil, errors.WithStack(err)
}
// Validate phase
phase, err := isv1.SnapshotPhaseFromString(res.Phase)
if err != nil {
return nil, errors.WithStack(err)
}
up := isv1.ProgressOutput{
Phase: phase,
Err: res.Err,
ItemsCompleted: res.ItemsCompleted,
ItemsToComplete: res.ItemsToComplete,
Started: time.Unix(res.Started, res.StartedNano),
Updated: time.Unix(res.Updated, res.UpdatedNano),
}
return &up, nil
}
func (recv ItemSnapshotterGRPCClient) DeleteSnapshot(ctx context.Context, input *isv1.DeleteSnapshotInput) error {
req := &proto.DeleteItemSnapshotRequest{
Plugin: recv.Plugin,
Params: input.Params,
SnapshotID: input.SnapshotID,
}
_, err := recv.grpcClient.DeleteSnapshot(ctx, req) // Returns Empty as first arg so just ignore
if err != nil {
return errors.WithStack(err)
}
return nil
}
func (recv ItemSnapshotterGRPCClient) CreateItemFromSnapshot(ctx context.Context, input *isv1.CreateItemInput) (*isv1.CreateItemOutput, error) {
itemJSON, err := json.Marshal(input.SnapshottedItem.UnstructuredContent())
if err != nil {
return nil, errors.WithStack(err)
}
itemFromBackupJSON, err := json.Marshal(input.ItemFromBackup.UnstructuredContent())
if err != nil {
return nil, errors.WithStack(err)
}
restoreJSON, err := json.Marshal(input.Restore)
if err != nil {
return nil, errors.WithStack(err)
}
req := &proto.CreateItemFromSnapshotRequest{
Plugin: recv.Plugin,
Item: itemJSON,
SnapshotID: input.SnapshotID,
ItemFromBackup: itemFromBackupJSON,
SnapshotMetadata: input.SnapshotMetadata,
Params: input.Params,
Restore: restoreJSON,
}
res, err := recv.grpcClient.CreateItemFromSnapshot(ctx, req)
if err != nil {
return nil, errors.WithStack(err)
}
var updatedItem unstructured.Unstructured
if err := json.Unmarshal(res.Item, &updatedItem); err != nil {
return nil, errors.WithStack(err)
}
additionalItems := unpackResourceIdentifiers(res.AdditionalItems)
cio := isv1.CreateItemOutput{
UpdatedItem: &updatedItem,
AdditionalItems: additionalItems,
SkipRestore: res.SkipRestore,
}
return &cio, nil
}
@@ -1,312 +0,0 @@
/*
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package framework
import (
"context"
"encoding/json"
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/pkg/errors"
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
proto "github.com/vmware-tanzu/velero/pkg/plugin/generated"
)
// ItemSnapshotterGRPCServer implements the proto-generated ItemSnapshotterServer interface, and accepts
// gRPC calls and forwards them to an implementation of the pluggable interface.
type ItemSnapshotterGRPCServer struct {
mux *common.ServerMux
}
func (recv *ItemSnapshotterGRPCServer) getImpl(name string) (isv1.ItemSnapshotter, error) {
impl, err := recv.mux.GetHandler(name)
if err != nil {
return nil, err
}
itemAction, ok := impl.(isv1.ItemSnapshotter)
if !ok {
return nil, errors.Errorf("%T is not an item snapshotter", impl)
}
return itemAction, nil
}
func (recv *ItemSnapshotterGRPCServer) Init(c context.Context, req *proto.ItemSnapshotterInitRequest) (response *proto.Empty, err error) {
defer func() {
if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil {
err = recoveredErr
}
}()
impl, err := recv.getImpl(req.Plugin)
if err != nil {
return nil, common.NewGRPCError(err)
}
err = impl.Init(req.Config)
if err != nil {
return nil, common.NewGRPCError(err)
}
return &proto.Empty{}, nil
}
func (recv *ItemSnapshotterGRPCServer) AppliesTo(ctx context.Context, req *proto.ItemSnapshotterAppliesToRequest) (response *proto.ItemSnapshotterAppliesToResponse, err error) {
defer func() {
if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil {
err = recoveredErr
}
}()
impl, err := recv.getImpl(req.Plugin)
if err != nil {
return nil, common.NewGRPCError(err)
}
resourceSelector, err := impl.AppliesTo()
if err != nil {
return nil, common.NewGRPCError(err)
}
return &proto.ItemSnapshotterAppliesToResponse{
ResourceSelector: &proto.ResourceSelector{
IncludedNamespaces: resourceSelector.IncludedNamespaces,
ExcludedNamespaces: resourceSelector.ExcludedNamespaces,
IncludedResources: resourceSelector.IncludedResources,
ExcludedResources: resourceSelector.ExcludedResources,
Selector: resourceSelector.LabelSelector,
},
}, nil
}
func (recv *ItemSnapshotterGRPCServer) AlsoHandles(ctx context.Context, req *proto.AlsoHandlesRequest) (res *proto.AlsoHandlesResponse, err error) {
defer func() {
if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil {
err = recoveredErr
}
}()
impl, err := recv.getImpl(req.Plugin)
if err != nil {
return nil, common.NewGRPCError(err)
}
var item unstructured.Unstructured
var backup api.Backup
if err := json.Unmarshal(req.Item, &item); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
if err := json.Unmarshal(req.Backup, &backup); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
ahi := isv1.AlsoHandlesInput{
Item: &item,
Backup: &backup,
}
alsoHandles, err := impl.AlsoHandles(&ahi)
if err != nil {
return nil, common.NewGRPCError(err)
}
res = &proto.AlsoHandlesResponse{}
for _, item := range alsoHandles {
res.HandledItems = append(res.HandledItems, resourceIdentifierToProto(item))
}
return res, nil
}
func (recv *ItemSnapshotterGRPCServer) SnapshotItem(ctx context.Context, req *proto.SnapshotItemRequest) (res *proto.SnapshotItemResponse, err error) {
defer func() {
if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil {
err = recoveredErr
}
}()
impl, err := recv.getImpl(req.Plugin)
if err != nil {
return nil, common.NewGRPCError(err)
}
var item unstructured.Unstructured
var backup api.Backup
if err := json.Unmarshal(req.Item, &item); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
if err := json.Unmarshal(req.Backup, &backup); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
sii := isv1.SnapshotItemInput{
Item: &item,
Params: req.Params,
Backup: &backup,
}
sio, err := impl.SnapshotItem(ctx, &sii)
// If the plugin implementation returned a nil updatedItem (meaning no modifications), reset updatedItem to the
// original item.
var updatedItemJSON []byte
if sio.UpdatedItem == nil {
updatedItemJSON = req.Item
} else {
updatedItemJSON, err = json.Marshal(sio.UpdatedItem.UnstructuredContent())
if err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
}
res = &proto.SnapshotItemResponse{
Item: updatedItemJSON,
SnapshotID: sio.SnapshotID,
SnapshotMetadata: sio.SnapshotMetadata,
}
res.AdditionalItems = packResourceIdentifiers(sio.AdditionalItems)
res.HandledItems = packResourceIdentifiers(sio.HandledItems)
return res, err
}
func (recv *ItemSnapshotterGRPCServer) Progress(ctx context.Context, req *proto.ProgressRequest) (res *proto.ProgressResponse, err error) {
defer func() {
if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil {
err = recoveredErr
}
}()
impl, err := recv.getImpl(req.Plugin)
if err != nil {
return nil, common.NewGRPCError(err)
}
var backup api.Backup
if err := json.Unmarshal(req.Backup, &backup); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
sipi := &isv1.ProgressInput{
ItemID: protoToResourceIdentifier(req.ItemID),
SnapshotID: req.SnapshotID,
Backup: &backup,
}
sipo, err := impl.Progress(sipi)
if err != nil {
return nil, common.NewGRPCError(err)
}
res = &proto.ProgressResponse{
Phase: string(sipo.Phase),
ItemsCompleted: sipo.ItemsCompleted,
ItemsToComplete: sipo.ItemsToComplete,
Started: sipo.Started.Unix(),
StartedNano: sipo.Started.UnixNano(),
Updated: sipo.Updated.Unix(),
UpdatedNano: sipo.Updated.UnixNano(),
Err: sipo.Err,
}
return res, nil
}
func (recv *ItemSnapshotterGRPCServer) DeleteSnapshot(ctx context.Context, req *proto.DeleteItemSnapshotRequest) (empty *proto.Empty, err error) {
defer func() {
if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil {
err = recoveredErr
}
}()
impl, err := recv.getImpl(req.Plugin)
if err != nil {
return nil, common.NewGRPCError(err)
}
var itemFromBackup unstructured.Unstructured
if err := json.Unmarshal(req.ItemFromBackup, &itemFromBackup); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
disi := isv1.DeleteSnapshotInput{
SnapshotID: req.SnapshotID,
ItemFromBackup: &itemFromBackup,
SnapshotMetadata: req.Metadata,
Params: req.Params,
}
err = impl.DeleteSnapshot(ctx, &disi)
if err != nil {
return nil, common.NewGRPCError(err)
}
return
}
func (recv *ItemSnapshotterGRPCServer) CreateItemFromSnapshot(ctx context.Context, req *proto.CreateItemFromSnapshotRequest) (res *proto.CreateItemFromSnapshotResponse, err error) {
defer func() {
if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil {
err = recoveredErr
}
}()
impl, err := recv.getImpl(req.Plugin)
if err != nil {
return nil, common.NewGRPCError(err)
}
var snapshottedItem unstructured.Unstructured
if err := json.Unmarshal(req.Item, &snapshottedItem); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
var itemFromBackup unstructured.Unstructured
if err := json.Unmarshal(req.Item, &itemFromBackup); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
var restore api.Restore
if err := json.Unmarshal(req.Restore, &restore); err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
cii := isv1.CreateItemInput{
SnapshottedItem: &snapshottedItem,
SnapshotID: req.SnapshotID,
ItemFromBackup: &itemFromBackup,
SnapshotMetadata: req.SnapshotMetadata,
Params: req.Params,
Restore: &restore,
}
cio, err := impl.CreateItemFromSnapshot(ctx, &cii)
if err != nil {
return nil, common.NewGRPCError(err)
}
var updatedItemJSON []byte
if cio.UpdatedItem == nil {
updatedItemJSON = req.Item
} else {
updatedItemJSON, err = json.Marshal(cio.UpdatedItem.UnstructuredContent())
if err != nil {
return nil, common.NewGRPCError(errors.WithStack(err))
}
}
res = &proto.CreateItemFromSnapshotResponse{
Item: updatedItemJSON,
SkipRestore: cio.SkipRestore,
}
res.AdditionalItems = packResourceIdentifiers(cio.AdditionalItems)
return
}
@@ -30,7 +30,6 @@ func TestPluginImplementationsAreGRPCPlugins(t *testing.T) {
new(ObjectStorePlugin),
new(PluginListerPlugin),
new(RestoreItemActionPlugin),
new(ItemSnapshotterPlugin),
}
for _, impl := range pluginImpls {
-20
View File
@@ -90,11 +90,6 @@ type Server interface {
// RegisterDeleteItemActions registers multiple Delete item actions.
RegisterDeleteItemActions(map[string]common.HandlerInitializer) Server
RegisterItemSnapshotter(pluginName string, initializer common.HandlerInitializer) Server
// RegisterItemSnapshotters registers multiple Item Snapshotters
RegisterItemSnapshotters(map[string]common.HandlerInitializer) Server
// Server runs the plugin server.
Serve()
}
@@ -111,7 +106,6 @@ type server struct {
restoreItemAction *RestoreItemActionPlugin
restoreItemActionV2 *riav2.RestoreItemActionPlugin
deleteItemAction *DeleteItemActionPlugin
itemSnapshotter *ItemSnapshotterPlugin
}
// NewServer returns a new Server
@@ -128,7 +122,6 @@ func NewServer() Server {
restoreItemAction: NewRestoreItemActionPlugin(common.ServerLogger(log)),
restoreItemActionV2: riav2.NewRestoreItemActionPlugin(common.ServerLogger(log)),
deleteItemAction: NewDeleteItemActionPlugin(common.ServerLogger(log)),
itemSnapshotter: NewItemSnapshotterPlugin(common.ServerLogger(log)),
}
}
@@ -224,17 +217,6 @@ func (s *server) RegisterDeleteItemActions(m map[string]common.HandlerInitialize
return s
}
func (s *server) RegisterItemSnapshotter(name string, initializer common.HandlerInitializer) Server {
s.itemSnapshotter.Register(name, initializer)
return s
}
func (s *server) RegisterItemSnapshotters(m map[string]common.HandlerInitializer) Server {
for name := range m {
s.RegisterItemSnapshotter(name, m[name])
}
return s
}
// getNames returns a list of PluginIdentifiers registered with plugin.
func getNames(command string, kind common.PluginKind, plugin Interface) []PluginIdentifier {
var pluginIdentifiers []PluginIdentifier
@@ -266,7 +248,6 @@ func (s *server) Serve() {
pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindRestoreItemAction, s.restoreItemAction)...)
pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindRestoreItemActionV2, s.restoreItemActionV2)...)
pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindDeleteItemAction, s.deleteItemAction)...)
pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindItemSnapshotter, s.itemSnapshotter)...)
pluginLister := NewPluginLister(pluginIdentifiers...)
@@ -281,7 +262,6 @@ func (s *server) Serve() {
string(common.PluginKindRestoreItemAction): s.restoreItemAction,
string(common.PluginKindRestoreItemActionV2): s.restoreItemActionV2,
string(common.PluginKindDeleteItemAction): s.deleteItemAction,
string(common.PluginKindItemSnapshotter): s.itemSnapshotter,
},
GRPCServer: plugin.DefaultGRPCServer,
})
File diff suppressed because it is too large Load Diff
-48
View File
@@ -4,8 +4,6 @@ package mocks
import (
mock "github.com/stretchr/testify/mock"
item_snapshotterv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
restoreitemactionv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/restoreitemaction/v1"
restoreitemactionv2 "github.com/vmware-tanzu/velero/pkg/plugin/velero/restoreitemaction/v2"
@@ -167,52 +165,6 @@ func (_m *Manager) GetDeleteItemActions() ([]velero.DeleteItemAction, error) {
return r0, r1
}
// GetItemSnapshotter provides a mock function with given fields: name
func (_m *Manager) GetItemSnapshotter(name string) (item_snapshotterv1.ItemSnapshotter, error) {
ret := _m.Called(name)
var r0 item_snapshotterv1.ItemSnapshotter
if rf, ok := ret.Get(0).(func(string) item_snapshotterv1.ItemSnapshotter); ok {
r0 = rf(name)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(item_snapshotterv1.ItemSnapshotter)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(name)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetItemSnapshotters provides a mock function with given fields:
func (_m *Manager) GetItemSnapshotters() ([]item_snapshotterv1.ItemSnapshotter, error) {
ret := _m.Called()
var r0 []item_snapshotterv1.ItemSnapshotter
if rf, ok := ret.Get(0).(func() []item_snapshotterv1.ItemSnapshotter); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]item_snapshotterv1.ItemSnapshotter)
}
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetObjectStore provides a mock function with given fields: name
func (_m *Manager) GetObjectStore(name string) (velero.ObjectStore, error) {
ret := _m.Called(name)
-95
View File
@@ -1,95 +0,0 @@
syntax = "proto3";
package generated;
option go_package = "github.com/vmware-tanzu/velero/pkg/plugin/generated";
import "Shared.proto";
message ItemSnapshotterAppliesToRequest {
string plugin = 1;
}
message ItemSnapshotterAppliesToResponse {
ResourceSelector ResourceSelector = 1;
}
message AlsoHandlesRequest {
string plugin = 1;
bytes item = 2;
bytes backup = 3;
}
message AlsoHandlesResponse {
repeated ResourceIdentifier handledItems = 1;
}
message SnapshotItemRequest {
string plugin = 1;
bytes item = 2;
map<string, string> params = 3;
bytes backup = 4;
}
message SnapshotItemResponse {
bytes item = 1;
string snapshotID = 2;
map<string, string> snapshotMetadata = 3;
repeated ResourceIdentifier additionalItems = 4;
repeated ResourceIdentifier handledItems = 5;
}
message ProgressRequest {
string plugin = 1;
ResourceIdentifier itemID = 2;
string snapshotID = 3;
bytes backup = 4;
}
message ProgressResponse {
string phase = 1;
int64 itemsCompleted = 2;
int64 itemsToComplete = 3;
int64 started = 4;
int64 startedNano = 5;
int64 updated = 6;
int64 updatedNano = 7;
string err = 8;
}
message DeleteItemSnapshotRequest {
string plugin = 1;
string snapshotID = 2;
bytes itemFromBackup = 3;
map<string, string> metadata = 4;
map<string, string> params = 5;
}
message CreateItemFromSnapshotRequest {
string plugin = 1;
bytes item = 2;
string snapshotID = 3;
bytes itemFromBackup = 4;
map<string, string> snapshotMetadata = 5;
map<string, string> params = 6;
bytes restore = 7;
}
message CreateItemFromSnapshotResponse {
bytes item = 1;
repeated ResourceIdentifier additionalItems = 2;
bool skipRestore = 3;
}
message ItemSnapshotterInitRequest {
string plugin = 1;
map<string, string> config = 2;
}
service ItemSnapshotter {
rpc Init(ItemSnapshotterInitRequest) returns (Empty);
rpc AppliesTo(ItemSnapshotterAppliesToRequest) returns (ItemSnapshotterAppliesToResponse);
rpc AlsoHandles(AlsoHandlesRequest) returns (AlsoHandlesResponse);
rpc SnapshotItem(SnapshotItemRequest) returns (SnapshotItemResponse);
rpc Progress(ProgressRequest) returns (ProgressResponse);
rpc DeleteSnapshot(DeleteItemSnapshotRequest) returns (Empty);
rpc CreateItemFromSnapshot(CreateItemFromSnapshotRequest) returns (CreateItemFromSnapshotResponse);
}
@@ -1,196 +0,0 @@
/*
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"context"
"fmt"
"time"
"k8s.io/apimachinery/pkg/runtime"
api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
)
type AlsoHandlesInput struct {
// Item is the item that will be snapshotted
Item runtime.Unstructured
// Backup is the representation of the backup resource being processed by Velero.
Backup *api.Backup
}
type SnapshotItemInput struct {
// Item is the item to snapshot
Item runtime.Unstructured
// Params are parameters to the snapshot
Params map[string]string
// Backup is the representation of the backup resource being processed by Velero.
Backup *api.Backup
}
type SnapshotItemOutput struct {
// UpdatedItem is the Item that should be included in the backup. It can optionally be modified during the Snapshot
UpdatedItem runtime.Unstructured
// SnapshotID identifies the snapshot that was taken
SnapshotID string
// SnapshotMetadata is information in addition to the SnapshotID that the
// plugin wants to store in the backup. SnapshotMetadata will be passed
// back in for DeleteSnapshot and CreateItemFromSnapshot
SnapshotMetadata map[string]string
// AdditionalItems are resources that need to be included in the backup to support this snapshhot
AdditionalItems []velero.ResourceIdentifier
// Items that were handled by this snapshot that should be excluded from the backup
HandledItems []velero.ResourceIdentifier
}
// ProgressInput contains the input parameters for the ItemSnapshotter's Progress function.
type ProgressInput struct {
// ItemID is the id of item that was stored in the backup
ItemID velero.ResourceIdentifier
// SnapshotID is the snapshot ID returned by ItemSnapshotter
SnapshotID string
// Backup is the representation of the backup resource being processed by Velero.
Backup *api.Backup
}
// SnapshotPhase is the lifecycle phase of a Velero item snapshot.
type SnapshotPhase string
const (
// SnapshotPhaseInProgress means the snapshot of the item has been taken and the point-in-time has been preserved,
// but the snapshot is not ready for use yet
SnapshotPhaseInProgress = SnapshotPhase("InProgress")
// SnapshotPhaseCompleted means the item snapshot was successfully created and can be restored from
SnapshotPhaseCompleted = SnapshotPhase("Completed")
// SnapshotPhaseFailed means the item snapshot was unable to be completed
SnapshotPhaseFailed = SnapshotPhase("Failed")
)
func SnapshotPhaseFromString(phase string) (SnapshotPhase, error) {
switch phase {
case string(SnapshotPhaseInProgress):
return SnapshotPhaseInProgress, nil
case string(SnapshotPhaseCompleted):
return SnapshotPhaseCompleted, nil
case string(SnapshotPhaseFailed):
return SnapshotPhaseFailed, nil
default:
return SnapshotPhase(""), fmt.Errorf("%s is not a valid SnapshotPhase", phase)
}
}
type ProgressOutput struct {
// Phase of the snapshot. If the phase is SnapshotPhaseFailed, the error will be in the Err string
Phase SnapshotPhase
// Err is a message about the error(s) that occurred during the processing of the snapshot
Err string
// ItemsCompleted is the number of items that have been completed in processing of the snapshot
// This is simply to show progress, when Phase goes to SnapshotPhaseCompleted ItemsCompleted and ItemsToComplete
// should be the same. This could be blocks to copy, files to copy, or anything else.
ItemsCompleted int64
// ItemsToComplete is the number of items that need to be completed
ItemsToComplete int64
// Started indicates when processing on the snapshot began (usually the time the snapshot was taken)
Started time.Time
// Updated indicates the time the status was last updated. Time 0 (time.Unix(0, 0)) is returned if unknown.
Updated time.Time
}
type DeleteSnapshotInput struct {
// SnapshotID is the snapshot to delete
SnapshotID string
// ItemFromBackup is the resource that was included in the backup
ItemFromBackup runtime.Unstructured
// SnapshotMetadata is the metadata that was returned when the snapshot was originally taken
SnapshotMetadata map[string]string
// Params are parameters to the deletion
Params map[string]string
}
type CreateItemInput struct {
// The snapshotted item at this stage of the restore (RestoreItemActions may
// have modified the item prior to CreateItemFromSnapshot being called)
SnapshottedItem runtime.Unstructured
// SnapshotID is the snapshot to create the item from
SnapshotID string
// ItemFromBackup is the snapshotted item that was stored in the backup
ItemFromBackup runtime.Unstructured
// SnapshotMetadata is the metadata that was returned when the snapshot was originally taken
SnapshotMetadata map[string]string
// Params are parameters to the deletion
Params map[string]string
// Restore is the representation of the restore resource being processed by Velero.
Restore *api.Restore
}
type CreateItemOutput struct {
// UpdatedItem is the item being restored mutated by ItemAction.
UpdatedItem runtime.Unstructured
// AdditionalItems is a list of additional related items that should
// be restored.
AdditionalItems []velero.ResourceIdentifier
// SkipRestore tells velero to stop executing further actions
// on this item, and skip the restore step. When this field's
// value is true, AdditionalItems will be ignored.
SkipRestore bool
}
// ItemSnapshotter handles snapshots on an individual item being backed up.
type ItemSnapshotter interface {
// Init prepares the ItemSnapshotter for usage using the provided map of
// configuration key-value pairs. It returns an error if the ItemSnapshotter
// cannot be initialized from the provided config.
Init(config map[string]string) error
// AppliesTo returns information about which resources this action should be invoked for.
// An ItemSnapshotter's SnapshotItem method will only be invoked on items that match the returned
// selector. A zero-valued ResourceSelector matches all resources.
AppliesTo() (velero.ResourceSelector, error)
// AlsoHandles is called for each item this ItemSnapshotter should handle and returns any items
// which will be handled by this plugin when snapshotting the item. These items will be excluded from the
// items being backed up. AlsoHandles will be called before SnapshotItem is called. For example, a database may expose
// a database resource that can be snapshotted. If the database uses a PVC that will be snapshotted/backed up as
// part of the database snapshot, that PVC should be returned when AlsoHandles is invoked. This is different from
// AdditionalItems (returned in SnapshotItemOutput and CreateItemOutput) which are specifying additional resources
// that Velero should store in the backup or create.
AlsoHandles(input *AlsoHandlesInput) ([]velero.ResourceIdentifier, error)
// SnapshotItem causes the ItemSnapshotter to snapshot the specified item. It may also
// perform arbitrary logic with the item being backed up, including mutating the item itself prior to backup.
// The item (unmodified or modified) should be returned, along with an optional slice of ResourceIdentifiers specifying
// additional related items that should be backed up.
// A caller can pass a context that includes a timeout. If the time to take the snapshot exceeds the
// time in the context, the plugin may abort the snapshot. The context timeout does not apply to upload
// time that occurs after SnapshotItem returns
SnapshotItem(ctx context.Context, input *SnapshotItemInput) (*SnapshotItemOutput, error)
// Progress will return the progress of a snapshot that is being uploaded
Progress(input *ProgressInput) (*ProgressOutput, error)
// DeleteSnapshot removes a snapshot
DeleteSnapshot(ctx context.Context, input *DeleteSnapshotInput) error
// CreateItemFromSnapshot creates a new item from the snapshot
CreateItemFromSnapshot(ctx context.Context, input *CreateItemInput) (*CreateItemOutput, error)
}
@@ -1,157 +0,0 @@
// Code generated by mockery v0.0.0-dev. DO NOT EDIT.
package mocks
import (
context "context"
mock "github.com/stretchr/testify/mock"
velero "github.com/vmware-tanzu/velero/pkg/plugin/velero"
v1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
)
// ItemSnapshotter is an autogenerated mock type for the ItemSnapshotter type
type ItemSnapshotter struct {
mock.Mock
}
// AlsoHandles provides a mock function with given fields: input
func (_m *ItemSnapshotter) AlsoHandles(input *v1.AlsoHandlesInput) ([]velero.ResourceIdentifier, error) {
ret := _m.Called(input)
var r0 []velero.ResourceIdentifier
if rf, ok := ret.Get(0).(func(*v1.AlsoHandlesInput) []velero.ResourceIdentifier); ok {
r0 = rf(input)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]velero.ResourceIdentifier)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*v1.AlsoHandlesInput) error); ok {
r1 = rf(input)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AppliesTo provides a mock function with given fields:
func (_m *ItemSnapshotter) AppliesTo() (velero.ResourceSelector, error) {
ret := _m.Called()
var r0 velero.ResourceSelector
if rf, ok := ret.Get(0).(func() velero.ResourceSelector); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(velero.ResourceSelector)
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// CreateItemFromSnapshot provides a mock function with given fields: ctx, input
func (_m *ItemSnapshotter) CreateItemFromSnapshot(ctx context.Context, input *v1.CreateItemInput) (*v1.CreateItemOutput, error) {
ret := _m.Called(ctx, input)
var r0 *v1.CreateItemOutput
if rf, ok := ret.Get(0).(func(context.Context, *v1.CreateItemInput) *v1.CreateItemOutput); ok {
r0 = rf(ctx, input)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1.CreateItemOutput)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *v1.CreateItemInput) error); ok {
r1 = rf(ctx, input)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// DeleteSnapshot provides a mock function with given fields: ctx, input
func (_m *ItemSnapshotter) DeleteSnapshot(ctx context.Context, input *v1.DeleteSnapshotInput) error {
ret := _m.Called(ctx, input)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *v1.DeleteSnapshotInput) error); ok {
r0 = rf(ctx, input)
} else {
r0 = ret.Error(0)
}
return r0
}
// Init provides a mock function with given fields: config
func (_m *ItemSnapshotter) Init(config map[string]string) error {
ret := _m.Called(config)
var r0 error
if rf, ok := ret.Get(0).(func(map[string]string) error); ok {
r0 = rf(config)
} else {
r0 = ret.Error(0)
}
return r0
}
// Progress provides a mock function with given fields: input
func (_m *ItemSnapshotter) Progress(input *v1.ProgressInput) (*v1.ProgressOutput, error) {
ret := _m.Called(input)
var r0 *v1.ProgressOutput
if rf, ok := ret.Get(0).(func(*v1.ProgressInput) *v1.ProgressOutput); ok {
r0 = rf(input)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1.ProgressOutput)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(*v1.ProgressInput) error); ok {
r1 = rf(input)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// SnapshotItem provides a mock function with given fields: ctx, input
func (_m *ItemSnapshotter) SnapshotItem(ctx context.Context, input *v1.SnapshotItemInput) (*v1.SnapshotItemOutput, error) {
ret := _m.Called(ctx, input)
var r0 *v1.SnapshotItemOutput
if rf, ok := ret.Get(0).(func(context.Context, *v1.SnapshotItemInput) *v1.SnapshotItemOutput); ok {
r0 = rf(ctx, input)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1.SnapshotItemOutput)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *v1.SnapshotItemInput) error); ok {
r1 = rf(ctx, input)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
+1 -11
View File
@@ -84,7 +84,6 @@ type Restorer interface {
RestoreWithResolvers(
req *Request,
restoreItemActionResolver framework.RestoreItemActionResolverV2,
itemSnapshotterResolver framework.ItemSnapshotterResolver,
volumeSnapshotterGetter VolumeSnapshotterGetter,
) (Result, Result)
}
@@ -159,14 +158,12 @@ func (kr *kubernetesRestorer) Restore(
volumeSnapshotterGetter VolumeSnapshotterGetter,
) (Result, Result) {
resolver := framework.NewRestoreItemActionResolverV2(actions)
snapshotItemResolver := framework.NewItemSnapshotterResolver(nil)
return kr.RestoreWithResolvers(req, resolver, snapshotItemResolver, volumeSnapshotterGetter)
return kr.RestoreWithResolvers(req, resolver, volumeSnapshotterGetter)
}
func (kr *kubernetesRestorer) RestoreWithResolvers(
req *Request,
restoreItemActionResolver framework.RestoreItemActionResolverV2,
itemSnapshotterResolver framework.ItemSnapshotterResolver,
volumeSnapshotterGetter VolumeSnapshotterGetter,
) (Result, Result) {
// metav1.LabelSelectorAsSelector converts a nil LabelSelector to a
@@ -222,11 +219,6 @@ func (kr *kubernetesRestorer) RestoreWithResolvers(
return Result{}, Result{Velero: []string{err.Error()}}
}
resolvedItemSnapshotterActions, err := itemSnapshotterResolver.ResolveActions(kr.discoveryHelper, kr.logger)
if err != nil {
return Result{}, Result{Velero: []string{err.Error()}}
}
podVolumeTimeout := kr.podVolumeTimeout
if val := req.Restore.Annotations[velerov1api.PodVolumeOperationTimeoutAnnotation]; val != "" {
parsed, err := time.ParseDuration(val)
@@ -291,7 +283,6 @@ func (kr *kubernetesRestorer) RestoreWithResolvers(
fileSystem: kr.fileSystem,
namespaceClient: kr.namespaceClient,
restoreItemActions: resolvedActions,
itemSnapshotterActions: resolvedItemSnapshotterActions,
volumeSnapshotterGetter: volumeSnapshotterGetter,
podVolumeRestorer: podVolumeRestorer,
podVolumeErrs: make(chan error),
@@ -335,7 +326,6 @@ type restoreContext struct {
fileSystem filesystem.Interface
namespaceClient corev1.NamespaceInterface
restoreItemActions []framework.RestoreItemResolvedActionV2
itemSnapshotterActions []framework.ItemSnapshotterResolvedAction
volumeSnapshotterGetter VolumeSnapshotterGetter
podVolumeRestorer podvolume.Restorer
podVolumeWaitGroup sync.WaitGroup