From 4262b475360419eb6679e92f7207ad5b56ea7125 Mon Sep 17 00:00:00 2001 From: Scott Seago Date: Wed, 31 Aug 2022 13:48:53 -0400 Subject: [PATCH 1/2] plugin/clientmgmt refactoring for BackupItemAction v1 Refactors the clientmgmt package to implement the plugin versioning changes needed for BIA v1 and overall package refactoring to support plugin versions in different packages. This should be all that's needed to move on to v2 for BackupItemAction. The remaining plugin types still need similar refactoring to what's being done here for BIA before attempting a v2 implementation. Signed-off-by: Scott Seago --- changelogs/unreleased/5271-sseago | 1 + pkg/cmd/server/server.go | 5 +- .../v1}/restartable_backup_item_action.go | 52 ++++-- .../restartable_backup_item_action_test.go | 27 +-- .../backupitemaction/v1/shared_test.go | 156 ++++++++++++++++++ pkg/plugin/clientmgmt/manager.go | 51 +++--- pkg/plugin/clientmgmt/manager_test.go | 96 +++++------ .../{ => process}/client_builder.go | 2 +- .../{ => process}/client_builder_test.go | 2 +- .../{ => process}/logrus_adapter.go | 2 +- .../{ => process}/logrus_adapter_test.go | 2 +- .../clientmgmt/{ => process}/process.go | 14 +- .../clientmgmt/{ => process}/process_test.go | 16 +- .../clientmgmt/{ => process}/registry.go | 28 ++-- .../clientmgmt/{ => process}/registry_test.go | 2 +- .../{ => process}/restartable_process.go | 56 +++---- .../clientmgmt/restartable_delegate_test.go | 11 +- .../restartable_delete_item_action.go | 15 +- .../restartable_delete_item_action_test.go | 19 ++- .../restartable_item_snapshotter.go | 18 +- .../restartable_item_snapshotter_test.go | 22 +-- .../clientmgmt/restartable_object_store.go | 19 ++- .../restartable_object_store_test.go | 31 ++-- .../restartable_restore_item_action.go | 17 +- .../restartable_restore_item_action_test.go | 19 ++- .../restartable_volume_snapshotter.go | 21 +-- .../restartable_volume_snapshotter_test.go | 31 ++-- pkg/plugin/mocks/process_factory.go | 20 ++- 28 files changed, 479 insertions(+), 276 deletions(-) create mode 100644 changelogs/unreleased/5271-sseago rename pkg/plugin/clientmgmt/{ => backupitemaction/v1}/restartable_backup_item_action.go (57%) rename pkg/plugin/clientmgmt/{ => backupitemaction/v1}/restartable_backup_item_action_test.go (82%) create mode 100644 pkg/plugin/clientmgmt/backupitemaction/v1/shared_test.go rename pkg/plugin/clientmgmt/{ => process}/client_builder.go (99%) rename pkg/plugin/clientmgmt/{ => process}/client_builder_test.go (99%) rename pkg/plugin/clientmgmt/{ => process}/logrus_adapter.go (99%) rename pkg/plugin/clientmgmt/{ => process}/logrus_adapter_test.go (99%) rename pkg/plugin/clientmgmt/{ => process}/process.go (93%) rename pkg/plugin/clientmgmt/{ => process}/process_test.go (92%) rename pkg/plugin/clientmgmt/{ => process}/registry.go (91%) rename pkg/plugin/clientmgmt/{ => process}/registry_test.go (99%) rename pkg/plugin/clientmgmt/{ => process}/restartable_process.go (75%) diff --git a/changelogs/unreleased/5271-sseago b/changelogs/unreleased/5271-sseago new file mode 100644 index 000000000..339b81b69 --- /dev/null +++ b/changelogs/unreleased/5271-sseago @@ -0,0 +1 @@ + plugin/clientmgmt refactoring for BackupItemAction v1 diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index 482e91731..3d09f7213 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -69,6 +69,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/metrics" "github.com/vmware-tanzu/velero/pkg/persistence" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/podexec" "github.com/vmware-tanzu/velero/pkg/restic" "github.com/vmware-tanzu/velero/pkg/restore" @@ -250,7 +251,7 @@ type server struct { cancelFunc context.CancelFunc logger logrus.FieldLogger logLevel logrus.Level - pluginRegistry clientmgmt.Registry + pluginRegistry process.Registry repoManager repository.Manager repoLocker *repository.RepoLocker repoEnsurer *repository.RepositoryEnsurer @@ -295,7 +296,7 @@ func newServer(f client.Factory, config serverConfig, logger *logrus.Logger) (*s return nil, err } - pluginRegistry := clientmgmt.NewRegistry(config.pluginDir, logger, logger.Level) + pluginRegistry := process.NewRegistry(config.pluginDir, logger, logger.Level) if err := pluginRegistry.DiscoverPlugins(); err != nil { return nil, err } diff --git a/pkg/plugin/clientmgmt/restartable_backup_item_action.go b/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action.go similarity index 57% rename from pkg/plugin/clientmgmt/restartable_backup_item_action.go rename to pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action.go index f9ff2faa3..3317be280 100644 --- a/pkg/plugin/clientmgmt/restartable_backup_item_action.go +++ b/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action.go @@ -14,40 +14,60 @@ See the License for the specific language governing permissions and limitations under the License. */ -package clientmgmt +package v1 import ( "github.com/pkg/errors" "k8s.io/apimachinery/pkg/runtime" api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" biav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v1" ) -// restartableBackupItemAction is a backup item action for a given implementation (such as "pod"). It is associated with +// AdaptedBackupItemAction is a backup item action adapted to the v1 BackupItemAction API +type AdaptedBackupItemAction struct { + Kind framework.PluginKind + + // Get returns a restartable BackupItemAction for the given name and process, wrapping if necessary + GetRestartable func(name string, restartableProcess process.RestartableProcess) biav1.BackupItemAction +} + +func AdaptedBackupItemActions() []AdaptedBackupItemAction { + return []AdaptedBackupItemAction{ + { + Kind: framework.PluginKindBackupItemAction, + GetRestartable: func(name string, restartableProcess process.RestartableProcess) biav1.BackupItemAction { + return NewRestartableBackupItemAction(name, restartableProcess) + }, + }, + } +} + +// RestartableBackupItemAction is a backup item action for a given implementation (such as "pod"). It is associated with // a restartableProcess, which may be shared and used to run multiple plugins. At the beginning of each method // call, the restartableBackupItemAction asks its restartableProcess to restart itself if needed (e.g. if the // process terminated for any reason), then it proceeds with the actual call. -type restartableBackupItemAction struct { - key kindAndName - sharedPluginProcess RestartableProcess +type RestartableBackupItemAction struct { + Key process.KindAndName + SharedPluginProcess process.RestartableProcess } -// newRestartableBackupItemAction returns a new restartableBackupItemAction. -func newRestartableBackupItemAction(name string, sharedPluginProcess RestartableProcess) *restartableBackupItemAction { - r := &restartableBackupItemAction{ - key: kindAndName{kind: framework.PluginKindBackupItemAction, name: name}, - sharedPluginProcess: sharedPluginProcess, +// NewRestartableBackupItemAction returns a new RestartableBackupItemAction. +func NewRestartableBackupItemAction(name string, sharedPluginProcess process.RestartableProcess) *RestartableBackupItemAction { + r := &RestartableBackupItemAction{ + Key: process.KindAndName{Kind: framework.PluginKindBackupItemAction, Name: name}, + SharedPluginProcess: sharedPluginProcess, } return r } // getBackupItemAction returns the backup item action for this restartableBackupItemAction. It does *not* restart the // plugin process. -func (r *restartableBackupItemAction) getBackupItemAction() (biav1.BackupItemAction, error) { - plugin, err := r.sharedPluginProcess.getByKindAndName(r.key) +func (r *RestartableBackupItemAction) getBackupItemAction() (biav1.BackupItemAction, error) { + plugin, err := r.SharedPluginProcess.GetByKindAndName(r.Key) if err != nil { return nil, err } @@ -61,8 +81,8 @@ func (r *restartableBackupItemAction) getBackupItemAction() (biav1.BackupItemAct } // getDelegate restarts the plugin process (if needed) and returns the backup item action for this restartableBackupItemAction. -func (r *restartableBackupItemAction) getDelegate() (biav1.BackupItemAction, error) { - if err := r.sharedPluginProcess.resetIfNeeded(); err != nil { +func (r *RestartableBackupItemAction) getDelegate() (biav1.BackupItemAction, error) { + if err := r.SharedPluginProcess.ResetIfNeeded(); err != nil { return nil, err } @@ -70,7 +90,7 @@ func (r *restartableBackupItemAction) getDelegate() (biav1.BackupItemAction, err } // AppliesTo restarts the plugin's process if needed, then delegates the call. -func (r *restartableBackupItemAction) AppliesTo() (velero.ResourceSelector, error) { +func (r *RestartableBackupItemAction) AppliesTo() (velero.ResourceSelector, error) { delegate, err := r.getDelegate() if err != nil { return velero.ResourceSelector{}, err @@ -80,7 +100,7 @@ func (r *restartableBackupItemAction) AppliesTo() (velero.ResourceSelector, erro } // Execute restarts the plugin's process if needed, then delegates the call. -func (r *restartableBackupItemAction) Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) { +func (r *RestartableBackupItemAction) Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) { delegate, err := r.getDelegate() if err != nil { return nil, nil, err diff --git a/pkg/plugin/clientmgmt/restartable_backup_item_action_test.go b/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action_test.go similarity index 82% rename from pkg/plugin/clientmgmt/restartable_backup_item_action_test.go rename to pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action_test.go index 7f528e73a..947a0f150 100644 --- a/pkg/plugin/clientmgmt/restartable_backup_item_action_test.go +++ b/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package clientmgmt +package v1 import ( "testing" @@ -27,6 +27,7 @@ import ( v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/backup/mocks" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -60,10 +61,10 @@ func TestRestartableGetBackupItemAction(t *testing.T) { defer p.AssertExpectations(t) name := "pod" - key := kindAndName{kind: framework.PluginKindBackupItemAction, name: name} - p.On("getByKindAndName", key).Return(tc.plugin, tc.getError) + key := process.KindAndName{Kind: framework.PluginKindBackupItemAction, Name: name} + p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) - r := newRestartableBackupItemAction(name, p) + r := NewRestartableBackupItemAction(name, p) a, err := r.getBackupItemAction() if tc.expectedError != "" { assert.EqualError(t, err, tc.expectedError) @@ -81,18 +82,18 @@ func TestRestartableBackupItemActionGetDelegate(t *testing.T) { defer p.AssertExpectations(t) // Reset error - p.On("resetIfNeeded").Return(errors.Errorf("reset error")).Once() + p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "pod" - r := newRestartableBackupItemAction(name, p) + r := NewRestartableBackupItemAction(name, p) a, err := r.getDelegate() assert.Nil(t, a) assert.EqualError(t, err, "reset error") // Happy path - p.On("resetIfNeeded").Return(nil) + p.On("ResetIfNeeded").Return(nil) expected := new(mocks.ItemAction) - key := kindAndName{kind: framework.PluginKindBackupItemAction, name: name} - p.On("getByKindAndName", key).Return(expected, nil) + key := process.KindAndName{Kind: framework.PluginKindBackupItemAction, Name: name} + p.On("GetByKindAndName", key).Return(expected, nil) a, err = r.getDelegate() assert.NoError(t, err) @@ -123,10 +124,10 @@ func TestRestartableBackupItemActionDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, framework.PluginKindBackupItemAction, - func(key kindAndName, p RestartableProcess) interface{} { - return &restartableBackupItemAction{ - key: key, - sharedPluginProcess: p, + func(key process.KindAndName, p process.RestartableProcess) interface{} { + return &RestartableBackupItemAction{ + Key: key, + SharedPluginProcess: p, } }, func() mockable { diff --git a/pkg/plugin/clientmgmt/backupitemaction/v1/shared_test.go b/pkg/plugin/clientmgmt/backupitemaction/v1/shared_test.go new file mode 100644 index 000000000..a612c764c --- /dev/null +++ b/pkg/plugin/clientmgmt/backupitemaction/v1/shared_test.go @@ -0,0 +1,156 @@ +/* +Copyright 2018 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 ( + "reflect" + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" + "github.com/vmware-tanzu/velero/pkg/plugin/framework" +) + +type mockRestartableProcess struct { + mock.Mock +} + +func (rp *mockRestartableProcess) AddReinitializer(key process.KindAndName, r process.Reinitializer) { + rp.Called(key, r) +} + +func (rp *mockRestartableProcess) Reset() error { + args := rp.Called() + return args.Error(0) +} + +func (rp *mockRestartableProcess) ResetIfNeeded() error { + args := rp.Called() + return args.Error(0) +} + +func (rp *mockRestartableProcess) GetByKindAndName(key process.KindAndName) (interface{}, error) { + args := rp.Called(key) + return args.Get(0), args.Error(1) +} + +func (rp *mockRestartableProcess) Stop() { + rp.Called() +} + +type restartableDelegateTest struct { + function string + inputs []interface{} + expectedErrorOutputs []interface{} + expectedDelegateOutputs []interface{} +} + +type mockable interface { + Test(t mock.TestingT) + On(method string, args ...interface{}) *mock.Call + AssertExpectations(t mock.TestingT) bool +} + +func runRestartableDelegateTests( + t *testing.T, + kind framework.PluginKind, + newRestartable func(key process.KindAndName, p process.RestartableProcess) interface{}, + newMock func() mockable, + tests ...restartableDelegateTest, +) { + for _, tc := range tests { + t.Run(tc.function, func(t *testing.T) { + p := new(mockRestartableProcess) + p.Test(t) + defer p.AssertExpectations(t) + + // getDelegate error + p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() + name := "delegateName" + key := process.KindAndName{Kind: kind, Name: name} + r := newRestartable(key, p) + + // Get the method we're going to call using reflection + method := reflect.ValueOf(r).MethodByName(tc.function) + require.NotEmpty(t, method) + + // Convert the test case inputs ([]interface{}) to []reflect.Value + var inputValues []reflect.Value + for i := range tc.inputs { + inputValues = append(inputValues, reflect.ValueOf(tc.inputs[i])) + } + + // Invoke the method being tested + actual := method.Call(inputValues) + + // This function asserts that the actual outputs match the expected outputs + checkOutputs := func(expected []interface{}, actual []reflect.Value) { + require.Equal(t, len(expected), len(actual)) + + for i := range actual { + // Get the underlying value from the reflect.Value + a := actual[i].Interface() + + // Check if it's an error + actualErr, actualErrOk := a.(error) + // Check if the expected output element is an error + expectedErr, expectedErrOk := expected[i].(error) + // If both are errors, use EqualError + if actualErrOk && expectedErrOk { + assert.EqualError(t, actualErr, expectedErr.Error()) + continue + } + + // If function returns nil as struct return type, we cannot just + // compare the interface to nil as its type will not be nil, + // only the value will be + if expected[i] == nil && reflect.ValueOf(a).Kind() == reflect.Ptr { + assert.True(t, reflect.ValueOf(a).IsNil()) + continue + } + + // Otherwise, use plain Equal + assert.Equal(t, expected[i], a) + } + } + + // Make sure we get what we expected when getDelegate returned an error + checkOutputs(tc.expectedErrorOutputs, actual) + + // Invoke delegate, make sure all returned values are passed through + p.On("ResetIfNeeded").Return(nil) + + delegate := newMock() + delegate.Test(t) + defer delegate.AssertExpectations(t) + + p.On("GetByKindAndName", key).Return(delegate, nil) + + // Set up the mocked method in the delegate + delegate.On(tc.function, tc.inputs...).Return(tc.expectedDelegateOutputs...) + + // Invoke the method being tested + actual = method.Call(inputValues) + + // Make sure we get what we expected when invoking the delegate + checkOutputs(tc.expectedDelegateOutputs, actual) + }) + } +} diff --git a/pkg/plugin/clientmgmt/manager.go b/pkg/plugin/clientmgmt/manager.go index 476608138..e2b55951c 100644 --- a/pkg/plugin/clientmgmt/manager.go +++ b/pkg/plugin/clientmgmt/manager.go @@ -17,11 +17,15 @@ limitations under the License. package clientmgmt import ( + "errors" + "fmt" "strings" "sync" "github.com/sirupsen/logrus" + biav1cli "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/backupitemaction/v1" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" biav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v1" @@ -36,7 +40,7 @@ type Manager interface { // GetVolumeSnapshotter returns the VolumeSnapshotter plugin for name. GetVolumeSnapshotter(name string) (velero.VolumeSnapshotter, error) - // GetBackupItemActions returns all backup item action plugins. + // GetBackupItemActions returns all v1 backup item action plugins. GetBackupItemActions() ([]biav1.BackupItemAction, error) // GetBackupItemAction returns the backup item action plugin for name. @@ -68,25 +72,25 @@ type Manager interface { type manager struct { logger logrus.FieldLogger logLevel logrus.Level - registry Registry + registry process.Registry - restartableProcessFactory RestartableProcessFactory + restartableProcessFactory process.RestartableProcessFactory // lock guards restartableProcesses lock sync.Mutex - restartableProcesses map[string]RestartableProcess + restartableProcesses map[string]process.RestartableProcess } // NewManager constructs a manager for getting plugins. -func NewManager(logger logrus.FieldLogger, level logrus.Level, registry Registry) Manager { +func NewManager(logger logrus.FieldLogger, level logrus.Level, registry process.Registry) Manager { return &manager{ logger: logger, logLevel: level, registry: registry, - restartableProcessFactory: newRestartableProcessFactory(), + restartableProcessFactory: process.NewRestartableProcessFactory(), - restartableProcesses: make(map[string]RestartableProcess), + restartableProcesses: make(map[string]process.RestartableProcess), } } @@ -94,7 +98,7 @@ func (m *manager) CleanupClients() { m.lock.Lock() for _, restartableProcess := range m.restartableProcesses { - restartableProcess.stop() + restartableProcess.Stop() } m.lock.Unlock() @@ -102,7 +106,7 @@ func (m *manager) CleanupClients() { // getRestartableProcess returns a restartableProcess for a plugin identified by kind and name, creating a // restartableProcess if it is the first time it has been requested. -func (m *manager) getRestartableProcess(kind framework.PluginKind, name string) (RestartableProcess, error) { +func (m *manager) getRestartableProcess(kind framework.PluginKind, name string) (process.RestartableProcess, error) { m.lock.Lock() defer m.lock.Unlock() @@ -127,7 +131,7 @@ func (m *manager) getRestartableProcess(kind framework.PluginKind, name string) logger.Debug("creating new restartable plugin process") - restartableProcess, err = m.restartableProcessFactory.newRestartableProcess(info.Command, m.logger, m.logLevel) + restartableProcess, err = m.restartableProcessFactory.NewRestartableProcess(info.Command, m.logger, m.logLevel) if err != nil { return nil, err } @@ -146,7 +150,7 @@ func (m *manager) GetObjectStore(name string) (velero.ObjectStore, error) { return nil, err } - r := newRestartableObjectStore(name, restartableProcess) + r := NewRestartableObjectStore(name, restartableProcess) return r, nil } @@ -160,7 +164,7 @@ func (m *manager) GetVolumeSnapshotter(name string) (velero.VolumeSnapshotter, e return nil, err } - r := newRestartableVolumeSnapshotter(name, restartableProcess) + r := NewRestartableVolumeSnapshotter(name, restartableProcess) return r, nil } @@ -189,13 +193,18 @@ func (m *manager) GetBackupItemActions() ([]biav1.BackupItemAction, error) { func (m *manager) GetBackupItemAction(name string) (biav1.BackupItemAction, error) { name = sanitizeName(name) - restartableProcess, err := m.getRestartableProcess(framework.PluginKindBackupItemAction, name) - if err != nil { - return nil, err + for _, adaptedBackupItemAction := range biav1cli.AdaptedBackupItemActions() { + restartableProcess, err := m.getRestartableProcess(adaptedBackupItemAction.Kind, name) + // Check if plugin was not found + if errors.Is(err, &process.PluginNotFoundError{}) { + continue + } + if err != nil { + return nil, err + } + return adaptedBackupItemAction.GetRestartable(name, restartableProcess), nil } - - r := newRestartableBackupItemAction(name, restartableProcess) - return r, nil + return nil, fmt.Errorf("unable to get valid BackupItemAction for %q", name) } // GetRestoreItemActions returns all restore item actions as restartableRestoreItemActions. @@ -227,7 +236,7 @@ func (m *manager) GetRestoreItemAction(name string) (velero.RestoreItemAction, e return nil, err } - r := newRestartableRestoreItemAction(name, restartableProcess) + r := NewRestartableRestoreItemAction(name, restartableProcess) return r, nil } @@ -260,7 +269,7 @@ func (m *manager) GetDeleteItemAction(name string) (velero.DeleteItemAction, err return nil, err } - r := newRestartableDeleteItemAction(name, restartableProcess) + r := NewRestartableDeleteItemAction(name, restartableProcess) return r, nil } @@ -272,7 +281,7 @@ func (m *manager) GetItemSnapshotter(name string) (isv1.ItemSnapshotter, error) return nil, err } - r := newRestartableItemSnapshotter(name, restartableProcess) + r := NewRestartableItemSnapshotter(name, restartableProcess) return r, nil } diff --git a/pkg/plugin/clientmgmt/manager_test.go b/pkg/plugin/clientmgmt/manager_test.go index cc36bc653..64b8bf4ed 100644 --- a/pkg/plugin/clientmgmt/manager_test.go +++ b/pkg/plugin/clientmgmt/manager_test.go @@ -26,6 +26,8 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + biav1cli "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/backupitemaction/v1" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/test" ) @@ -72,11 +74,11 @@ type mockRestartableProcessFactory struct { mock.Mock } -func (f *mockRestartableProcessFactory) newRestartableProcess(command string, logger logrus.FieldLogger, logLevel logrus.Level) (RestartableProcess, error) { +func (f *mockRestartableProcessFactory) NewRestartableProcess(command string, logger logrus.FieldLogger, logLevel logrus.Level) (process.RestartableProcess, error) { args := f.Called(command, logger, logLevel) - var rp RestartableProcess + var rp process.RestartableProcess if args.Get(0) != nil { - rp = args.Get(0).(RestartableProcess) + rp = args.Get(0).(process.RestartableProcess) } return rp, args.Error(1) } @@ -85,26 +87,26 @@ type mockRestartableProcess struct { mock.Mock } -func (rp *mockRestartableProcess) addReinitializer(key kindAndName, r reinitializer) { +func (rp *mockRestartableProcess) AddReinitializer(key process.KindAndName, r process.Reinitializer) { rp.Called(key, r) } -func (rp *mockRestartableProcess) reset() error { +func (rp *mockRestartableProcess) Reset() error { args := rp.Called() return args.Error(0) } -func (rp *mockRestartableProcess) resetIfNeeded() error { +func (rp *mockRestartableProcess) ResetIfNeeded() error { args := rp.Called() return args.Error(0) } -func (rp *mockRestartableProcess) getByKindAndName(key kindAndName) (interface{}, error) { +func (rp *mockRestartableProcess) GetByKindAndName(key process.KindAndName) (interface{}, error) { args := rp.Called(key) return args.Get(0), args.Error(1) } -func (rp *mockRestartableProcess) stop() { +func (rp *mockRestartableProcess) Stop() { rp.Called() } @@ -135,7 +137,7 @@ func TestGetRestartableProcess(t *testing.T) { Name: pluginName, } registry.On("Get", pluginKind, pluginName).Return(podID, nil) - factory.On("newRestartableProcess", podID.Command, logger, logLevel).Return(nil, errors.Errorf("factory")).Once() + factory.On("NewRestartableProcess", podID.Command, logger, logLevel).Return(nil, errors.Errorf("factory")).Once() rp, err = m.getRestartableProcess(pluginKind, pluginName) assert.Nil(t, rp) assert.EqualError(t, err, "factory") @@ -143,7 +145,7 @@ func TestGetRestartableProcess(t *testing.T) { // Test 3: registry ok, factory ok restartableProcess := &mockRestartableProcess{} defer restartableProcess.AssertExpectations(t) - factory.On("newRestartableProcess", podID.Command, logger, logLevel).Return(restartableProcess, nil).Once() + factory.On("NewRestartableProcess", podID.Command, logger, logLevel).Return(restartableProcess, nil).Once() rp, err = m.getRestartableProcess(pluginKind, pluginName) require.NoError(t, err) assert.Equal(t, restartableProcess, rp) @@ -166,7 +168,7 @@ func TestCleanupClients(t *testing.T) { for i := 0; i < 5; i++ { rp := &mockRestartableProcess{} defer rp.AssertExpectations(t) - rp.On("stop") + rp.On("Stop") m.restartableProcesses[fmt.Sprintf("rp%d", i)] = rp } @@ -180,9 +182,9 @@ func TestGetObjectStore(t *testing.T) { func(m Manager, name string) (interface{}, error) { return m.GetObjectStore(name) }, - func(name string, sharedPluginProcess RestartableProcess) interface{} { + func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &restartableObjectStore{ - key: kindAndName{kind: framework.PluginKindObjectStore, name: name}, + key: process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name}, sharedPluginProcess: sharedPluginProcess, } }, @@ -197,9 +199,9 @@ func TestGetVolumeSnapshotter(t *testing.T) { func(m Manager, name string) (interface{}, error) { return m.GetVolumeSnapshotter(name) }, - func(name string, sharedPluginProcess RestartableProcess) interface{} { + func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &restartableVolumeSnapshotter{ - key: kindAndName{kind: framework.PluginKindVolumeSnapshotter, name: name}, + key: process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name}, sharedPluginProcess: sharedPluginProcess, } }, @@ -214,10 +216,10 @@ func TestGetBackupItemAction(t *testing.T) { func(m Manager, name string) (interface{}, error) { return m.GetBackupItemAction(name) }, - func(name string, sharedPluginProcess RestartableProcess) interface{} { - return &restartableBackupItemAction{ - key: kindAndName{kind: framework.PluginKindBackupItemAction, name: name}, - sharedPluginProcess: sharedPluginProcess, + func(name string, sharedPluginProcess process.RestartableProcess) interface{} { + return &biav1cli.RestartableBackupItemAction{ + Key: process.KindAndName{Kind: framework.PluginKindBackupItemAction, Name: name}, + SharedPluginProcess: sharedPluginProcess, } }, false, @@ -231,9 +233,9 @@ func TestGetRestoreItemAction(t *testing.T) { func(m Manager, name string) (interface{}, error) { return m.GetRestoreItemAction(name) }, - func(name string, sharedPluginProcess RestartableProcess) interface{} { + func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &restartableRestoreItemAction{ - key: kindAndName{kind: framework.PluginKindRestoreItemAction, name: name}, + key: process.KindAndName{Kind: framework.PluginKindRestoreItemAction, Name: name}, sharedPluginProcess: sharedPluginProcess, } }, @@ -246,7 +248,7 @@ func getPluginTest( kind framework.PluginKind, name string, getPluginFunc func(m Manager, name string) (interface{}, error), - expectedResultFunc func(name string, sharedPluginProcess RestartableProcess) interface{}, + expectedResultFunc func(name string, sharedPluginProcess process.RestartableProcess) interface{}, reinitializable bool, ) { logger := test.NewLogger() @@ -273,18 +275,18 @@ func getPluginTest( defer restartableProcess.AssertExpectations(t) // Test 1: error getting restartable process - factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(nil, errors.Errorf("newRestartableProcess")).Once() + factory.On("NewRestartableProcess", pluginID.Command, logger, logLevel).Return(nil, errors.Errorf("NewRestartableProcess")).Once() actual, err := getPluginFunc(m, pluginName) assert.Nil(t, actual) - assert.EqualError(t, err, "newRestartableProcess") + assert.EqualError(t, err, "NewRestartableProcess") // Test 2: happy path - factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() + factory.On("NewRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() expected := expectedResultFunc(name, restartableProcess) if reinitializable { - key := kindAndName{kind: pluginID.Kind, name: pluginID.Name} - restartableProcess.On("addReinitializer", key, expected) + key := process.KindAndName{Kind: pluginID.Kind, Name: pluginID.Name} + restartableProcess.On("AddReinitializer", key, expected) } actual, err = getPluginFunc(m, pluginName) @@ -306,8 +308,8 @@ func TestGetBackupItemActions(t *testing.T) { { name: "Error getting restartable process", names: []string{"velero.io/a", "velero.io/b", "velero.io/c"}, - newRestartableProcessError: errors.Errorf("newRestartableProcess"), - expectedError: "newRestartableProcess", + newRestartableProcessError: errors.Errorf("NewRestartableProcess"), + expectedError: "NewRestartableProcess", }, { name: "Happy path", @@ -349,20 +351,20 @@ func TestGetBackupItemActions(t *testing.T) { restartableProcess := &mockRestartableProcess{} defer restartableProcess.AssertExpectations(t) - expected := &restartableBackupItemAction{ - key: kindAndName{kind: pluginKind, name: pluginName}, - sharedPluginProcess: restartableProcess, + expected := &biav1cli.RestartableBackupItemAction{ + Key: process.KindAndName{Kind: pluginKind, Name: pluginName}, + SharedPluginProcess: restartableProcess, } if tc.newRestartableProcessError != nil { // Test 1: error getting restartable process - factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(nil, errors.Errorf("newRestartableProcess")).Once() + factory.On("NewRestartableProcess", pluginID.Command, logger, logLevel).Return(nil, errors.Errorf("NewRestartableProcess")).Once() break } // Test 2: happy path if i == 0 { - factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() + factory.On("NewRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() } expectedActions = append(expectedActions, expected) @@ -371,7 +373,7 @@ func TestGetBackupItemActions(t *testing.T) { backupItemActions, err := m.GetBackupItemActions() if tc.newRestartableProcessError != nil { assert.Nil(t, backupItemActions) - assert.EqualError(t, err, "newRestartableProcess") + assert.EqualError(t, err, "NewRestartableProcess") } else { require.NoError(t, err) var actual []interface{} @@ -398,8 +400,8 @@ func TestGetRestoreItemActions(t *testing.T) { { name: "Error getting restartable process", names: []string{"velero.io/a", "velero.io/b", "velero.io/c"}, - newRestartableProcessError: errors.Errorf("newRestartableProcess"), - expectedError: "newRestartableProcess", + newRestartableProcessError: errors.Errorf("NewRestartableProcess"), + expectedError: "NewRestartableProcess", }, { name: "Happy path", @@ -442,19 +444,19 @@ func TestGetRestoreItemActions(t *testing.T) { defer restartableProcess.AssertExpectations(t) expected := &restartableRestoreItemAction{ - key: kindAndName{kind: pluginKind, name: pluginName}, + key: process.KindAndName{Kind: pluginKind, Name: pluginName}, sharedPluginProcess: restartableProcess, } if tc.newRestartableProcessError != nil { // Test 1: error getting restartable process - factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(nil, errors.Errorf("newRestartableProcess")).Once() + factory.On("NewRestartableProcess", pluginID.Command, logger, logLevel).Return(nil, errors.Errorf("NewRestartableProcess")).Once() break } // Test 2: happy path if i == 0 { - factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() + factory.On("NewRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() } expectedActions = append(expectedActions, expected) @@ -463,7 +465,7 @@ func TestGetRestoreItemActions(t *testing.T) { restoreItemActions, err := m.GetRestoreItemActions() if tc.newRestartableProcessError != nil { assert.Nil(t, restoreItemActions) - assert.EqualError(t, err, "newRestartableProcess") + assert.EqualError(t, err, "NewRestartableProcess") } else { require.NoError(t, err) var actual []interface{} @@ -483,9 +485,9 @@ func TestGetDeleteItemAction(t *testing.T) { func(m Manager, name string) (interface{}, error) { return m.GetDeleteItemAction(name) }, - func(name string, sharedPluginProcess RestartableProcess) interface{} { + func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &restartableDeleteItemAction{ - key: kindAndName{kind: framework.PluginKindDeleteItemAction, name: name}, + key: process.KindAndName{Kind: framework.PluginKindDeleteItemAction, Name: name}, sharedPluginProcess: sharedPluginProcess, } }, @@ -541,19 +543,19 @@ func TestGetDeleteItemActions(t *testing.T) { defer restartableProcess.AssertExpectations(t) expected := &restartableRestoreItemAction{ - key: kindAndName{kind: pluginKind, name: pluginName}, + key: process.KindAndName{Kind: pluginKind, Name: pluginName}, sharedPluginProcess: restartableProcess, } if tc.newRestartableProcessError != nil { // Test 1: error getting restartable process - factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(nil, errors.Errorf("newRestartableProcess")).Once() + factory.On("NewRestartableProcess", pluginID.Command, logger, logLevel).Return(nil, errors.Errorf("NewRestartableProcess")).Once() break } // Test 2: happy path if i == 0 { - factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() + factory.On("NewRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() } expectedActions = append(expectedActions, expected) @@ -562,7 +564,7 @@ func TestGetDeleteItemActions(t *testing.T) { deleteItemActions, err := m.GetDeleteItemActions() if tc.newRestartableProcessError != nil { assert.Nil(t, deleteItemActions) - assert.EqualError(t, err, "newRestartableProcess") + assert.EqualError(t, err, "NewRestartableProcess") } else { require.NoError(t, err) var actual []interface{} diff --git a/pkg/plugin/clientmgmt/client_builder.go b/pkg/plugin/clientmgmt/process/client_builder.go similarity index 99% rename from pkg/plugin/clientmgmt/client_builder.go rename to pkg/plugin/clientmgmt/process/client_builder.go index 76e3b1985..0d3948807 100644 --- a/pkg/plugin/clientmgmt/client_builder.go +++ b/pkg/plugin/clientmgmt/process/client_builder.go @@ -15,7 +15,7 @@ limitations under the License. */ // Package clientmgmt contains the plugin client for Velero. -package clientmgmt +package process import ( "os" diff --git a/pkg/plugin/clientmgmt/client_builder_test.go b/pkg/plugin/clientmgmt/process/client_builder_test.go similarity index 99% rename from pkg/plugin/clientmgmt/client_builder_test.go rename to pkg/plugin/clientmgmt/process/client_builder_test.go index e922c3d00..1b9c77145 100644 --- a/pkg/plugin/clientmgmt/client_builder_test.go +++ b/pkg/plugin/clientmgmt/process/client_builder_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package clientmgmt +package process import ( "os" diff --git a/pkg/plugin/clientmgmt/logrus_adapter.go b/pkg/plugin/clientmgmt/process/logrus_adapter.go similarity index 99% rename from pkg/plugin/clientmgmt/logrus_adapter.go rename to pkg/plugin/clientmgmt/process/logrus_adapter.go index 3bb55d464..cb73da789 100644 --- a/pkg/plugin/clientmgmt/logrus_adapter.go +++ b/pkg/plugin/clientmgmt/process/logrus_adapter.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package clientmgmt +package process import ( "fmt" diff --git a/pkg/plugin/clientmgmt/logrus_adapter_test.go b/pkg/plugin/clientmgmt/process/logrus_adapter_test.go similarity index 99% rename from pkg/plugin/clientmgmt/logrus_adapter_test.go rename to pkg/plugin/clientmgmt/process/logrus_adapter_test.go index ccfdfa828..dae7f8ce2 100644 --- a/pkg/plugin/clientmgmt/logrus_adapter_test.go +++ b/pkg/plugin/clientmgmt/process/logrus_adapter_test.go @@ -13,7 +13,7 @@ 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 +package process import ( "testing" diff --git a/pkg/plugin/clientmgmt/process.go b/pkg/plugin/clientmgmt/process/process.go similarity index 93% rename from pkg/plugin/clientmgmt/process.go rename to pkg/plugin/clientmgmt/process/process.go index f2fc8ae36..66033768d 100644 --- a/pkg/plugin/clientmgmt/process.go +++ b/pkg/plugin/clientmgmt/process/process.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package clientmgmt +package process import ( "strings" @@ -42,7 +42,7 @@ func (pf *processFactory) newProcess(command string, logger logrus.FieldLogger, } type Process interface { - dispense(key kindAndName) (interface{}, error) + dispense(key KindAndName) (interface{}, error) exited() bool kill() } @@ -124,21 +124,21 @@ func removeFeaturesFlag(args []string) []string { return commandArgs } -func (r *process) dispense(key kindAndName) (interface{}, error) { +func (r *process) dispense(key KindAndName) (interface{}, error) { // This calls GRPCClient(clientConn) on the plugin instance registered for key.name. - dispensed, err := r.protocolClient.Dispense(key.kind.String()) + dispensed, err := r.protocolClient.Dispense(key.Kind.String()) if err != nil { return nil, errors.WithStack(err) } // Currently all plugins except for PluginLister dispense clientDispenser instances. if clientDispenser, ok := dispensed.(framework.ClientDispenser); ok { - if key.name == "" { - return nil, errors.Errorf("%s plugin requested but name is missing", key.kind.String()) + if key.Name == "" { + return nil, errors.Errorf("%s plugin requested but name is missing", key.Kind.String()) } // Get the instance that implements our plugin interface (e.g. ObjectStore) that is a gRPC-based // client - dispensed = clientDispenser.ClientFor(key.name) + dispensed = clientDispenser.ClientFor(key.Name) } return dispensed, nil diff --git a/pkg/plugin/clientmgmt/process_test.go b/pkg/plugin/clientmgmt/process/process_test.go similarity index 92% rename from pkg/plugin/clientmgmt/process_test.go rename to pkg/plugin/clientmgmt/process/process_test.go index ac82ade87..a44254dbd 100644 --- a/pkg/plugin/clientmgmt/process_test.go +++ b/pkg/plugin/clientmgmt/process/process_test.go @@ -13,7 +13,7 @@ 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 +package process import ( "testing" @@ -94,20 +94,20 @@ func TestDispense(t *testing.T) { var client interface{} - key := kindAndName{} + key := KindAndName{} if tc.clientDispenser { - key.kind = framework.PluginKindObjectStore - protocolClient.On("Dispense", key.kind.String()).Return(clientDispenser, tc.dispenseError) + key.Kind = framework.PluginKindObjectStore + protocolClient.On("Dispense", key.Kind.String()).Return(clientDispenser, tc.dispenseError) if !tc.missingKeyName { - key.name = "aws" + key.Name = "aws" client = &framework.BackupItemActionGRPCClient{} - clientDispenser.On("ClientFor", key.name).Return(client) + clientDispenser.On("ClientFor", key.Name).Return(client) } } else { - key.kind = framework.PluginKindPluginLister + key.Kind = framework.PluginKindPluginLister client = &framework.PluginListerGRPCClient{} - protocolClient.On("Dispense", key.kind.String()).Return(client, tc.dispenseError) + protocolClient.On("Dispense", key.Kind.String()).Return(client, tc.dispenseError) } dispensed, err := p.dispense(key) diff --git a/pkg/plugin/clientmgmt/registry.go b/pkg/plugin/clientmgmt/process/registry.go similarity index 91% rename from pkg/plugin/clientmgmt/registry.go rename to pkg/plugin/clientmgmt/process/registry.go index fe8a7f4b4..2e51ea2a2 100644 --- a/pkg/plugin/clientmgmt/registry.go +++ b/pkg/plugin/clientmgmt/process/registry.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package clientmgmt +package process import ( "fmt" @@ -38,10 +38,10 @@ type Registry interface { Get(kind framework.PluginKind, name string) (framework.PluginIdentifier, error) } -// kindAndName is a convenience struct that combines a PluginKind and a name. -type kindAndName struct { - kind framework.PluginKind - name string +// KindAndName is a convenience struct that combines a PluginKind and a name. +type KindAndName struct { + Kind framework.PluginKind + Name string } // registry implements Registry. @@ -53,7 +53,7 @@ type registry struct { processFactory ProcessFactory fs filesystem.Interface - pluginsByID map[kindAndName]framework.PluginIdentifier + pluginsByID map[KindAndName]framework.PluginIdentifier pluginsByKind map[framework.PluginKind][]framework.PluginIdentifier } @@ -66,7 +66,7 @@ func NewRegistry(dir string, logger logrus.FieldLogger, logLevel logrus.Level) R processFactory: newProcessFactory(), fs: filesystem.NewFileSystem(), - pluginsByID: make(map[kindAndName]framework.PluginIdentifier), + pluginsByID: make(map[KindAndName]framework.PluginIdentifier), pluginsByKind: make(map[framework.PluginKind][]framework.PluginIdentifier), } } @@ -117,7 +117,7 @@ func (r *registry) List(kind framework.PluginKind) []framework.PluginIdentifier // Get returns info about a plugin with the given name and kind, or an // error if one cannot be found. func (r *registry) Get(kind framework.PluginKind, name string) (framework.PluginIdentifier, error) { - p, found := r.pluginsByID[kindAndName{kind: kind, name: name}] + p, found := r.pluginsByID[KindAndName{Kind: kind, Name: name}] if !found { return framework.PluginIdentifier{}, newPluginNotFoundError(kind, name) } @@ -182,7 +182,7 @@ func (r *registry) listPlugins(command string) ([]framework.PluginIdentifier, er } defer process.kill() - plugin, err := process.dispense(kindAndName{kind: framework.PluginKindPluginLister}) + plugin, err := process.dispense(KindAndName{Kind: framework.PluginKindPluginLister}) if err != nil { return nil, err } @@ -197,7 +197,7 @@ func (r *registry) listPlugins(command string) ([]framework.PluginIdentifier, er // register registers a PluginIdentifier with the registry. func (r *registry) register(id framework.PluginIdentifier) error { - key := kindAndName{kind: id.Kind, name: id.Name} + key := KindAndName{Kind: id.Kind, Name: id.Name} if existing, found := r.pluginsByID[key]; found { return newDuplicatePluginRegistrationError(existing, id) } @@ -214,20 +214,20 @@ func (r *registry) register(id framework.PluginIdentifier) error { } // pluginNotFoundError indicates a plugin could not be located for kind and name. -type pluginNotFoundError struct { +type PluginNotFoundError struct { kind framework.PluginKind name string } // newPluginNotFoundError returns a new pluginNotFoundError for kind and name. -func newPluginNotFoundError(kind framework.PluginKind, name string) *pluginNotFoundError { - return &pluginNotFoundError{ +func newPluginNotFoundError(kind framework.PluginKind, name string) *PluginNotFoundError { + return &PluginNotFoundError{ kind: kind, name: name, } } -func (e *pluginNotFoundError) Error() string { +func (e *PluginNotFoundError) Error() string { return fmt.Sprintf("unable to locate %v plugin named %s", e.kind, e.name) } diff --git a/pkg/plugin/clientmgmt/registry_test.go b/pkg/plugin/clientmgmt/process/registry_test.go similarity index 99% rename from pkg/plugin/clientmgmt/registry_test.go rename to pkg/plugin/clientmgmt/process/registry_test.go index 45bbcbb89..cd0614f85 100644 --- a/pkg/plugin/clientmgmt/registry_test.go +++ b/pkg/plugin/clientmgmt/process/registry_test.go @@ -13,7 +13,7 @@ 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 +package process import ( "os" diff --git a/pkg/plugin/clientmgmt/restartable_process.go b/pkg/plugin/clientmgmt/process/restartable_process.go similarity index 75% rename from pkg/plugin/clientmgmt/restartable_process.go rename to pkg/plugin/clientmgmt/process/restartable_process.go index 54211d8d1..21ed81022 100644 --- a/pkg/plugin/clientmgmt/restartable_process.go +++ b/pkg/plugin/clientmgmt/process/restartable_process.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package clientmgmt +package process import ( "sync" @@ -24,26 +24,26 @@ import ( ) type RestartableProcessFactory interface { - newRestartableProcess(command string, logger logrus.FieldLogger, logLevel logrus.Level) (RestartableProcess, error) + NewRestartableProcess(command string, logger logrus.FieldLogger, logLevel logrus.Level) (RestartableProcess, error) } type restartableProcessFactory struct { } -func newRestartableProcessFactory() RestartableProcessFactory { +func NewRestartableProcessFactory() RestartableProcessFactory { return &restartableProcessFactory{} } -func (rpf *restartableProcessFactory) newRestartableProcess(command string, logger logrus.FieldLogger, logLevel logrus.Level) (RestartableProcess, error) { +func (rpf *restartableProcessFactory) NewRestartableProcess(command string, logger logrus.FieldLogger, logLevel logrus.Level) (RestartableProcess, error) { return newRestartableProcess(command, logger, logLevel) } type RestartableProcess interface { - addReinitializer(key kindAndName, r reinitializer) - reset() error - resetIfNeeded() error - getByKindAndName(key kindAndName) (interface{}, error) - stop() + AddReinitializer(key KindAndName, r Reinitializer) + Reset() error + ResetIfNeeded() error + GetByKindAndName(key KindAndName) (interface{}, error) + Stop() } // restartableProcess encapsulates the lifecycle for all plugins contained in a single executable file. It is able @@ -57,15 +57,15 @@ type restartableProcess struct { // lock guards all of the fields below lock sync.RWMutex process Process - plugins map[kindAndName]interface{} - reinitializers map[kindAndName]reinitializer + plugins map[KindAndName]interface{} + reinitializers map[KindAndName]Reinitializer resetFailures int } // reinitializer is capable of reinitializing a restartable plugin instance using the newly dispensed plugin. -type reinitializer interface { +type Reinitializer interface { // reinitialize reinitializes a restartable plugin instance using the newly dispensed plugin. - reinitialize(dispensed interface{}) error + Reinitialize(dispensed interface{}) error } // newRestartableProcess creates a new restartableProcess for the given command and options. @@ -74,26 +74,26 @@ func newRestartableProcess(command string, logger logrus.FieldLogger, logLevel l command: command, logger: logger, logLevel: logLevel, - plugins: make(map[kindAndName]interface{}), - reinitializers: make(map[kindAndName]reinitializer), + plugins: make(map[KindAndName]interface{}), + reinitializers: make(map[KindAndName]Reinitializer), } // This launches the process - err := p.reset() + err := p.Reset() return p, err } -// addReinitializer registers the reinitializer r for key. -func (p *restartableProcess) addReinitializer(key kindAndName, r reinitializer) { +// AddReinitializer registers the reinitializer r for key. +func (p *restartableProcess) AddReinitializer(key KindAndName, r Reinitializer) { p.lock.Lock() defer p.lock.Unlock() p.reinitializers[key] = r } -// reset acquires the lock and calls resetLH. -func (p *restartableProcess) reset() error { +// Reset acquires the lock and calls resetLH. +func (p *restartableProcess) Reset() error { p.lock.Lock() defer p.lock.Unlock() @@ -118,7 +118,7 @@ func (p *restartableProcess) resetLH() error { // Redispense any previously dispensed plugins, reinitializing if necessary. // Start by creating a new map to hold the newly dispensed plugins. - newPlugins := make(map[kindAndName]interface{}) + newPlugins := make(map[KindAndName]interface{}) for key := range p.plugins { // Re-dispense dispensed, err := p.process.dispense(key) @@ -131,7 +131,7 @@ func (p *restartableProcess) resetLH() error { // Reinitialize if r, found := p.reinitializers[key]; found { - if err := r.reinitialize(dispensed); err != nil { + if err := r.Reinitialize(dispensed); err != nil { p.resetFailures++ return err } @@ -146,8 +146,8 @@ func (p *restartableProcess) resetLH() error { return nil } -// resetIfNeeded checks if the plugin process has exited and resets p if it has. -func (p *restartableProcess) resetIfNeeded() error { +// ResetIfNeeded checks if the plugin process has exited and resets p if it has. +func (p *restartableProcess) ResetIfNeeded() error { p.lock.Lock() defer p.lock.Unlock() @@ -159,8 +159,8 @@ func (p *restartableProcess) resetIfNeeded() error { return nil } -// getByKindAndName acquires the lock and calls getByKindAndNameLH. -func (p *restartableProcess) getByKindAndName(key kindAndName) (interface{}, error) { +// GetByKindAndName acquires the lock and calls getByKindAndNameLH. +func (p *restartableProcess) GetByKindAndName(key KindAndName) (interface{}, error) { p.lock.Lock() defer p.lock.Unlock() @@ -169,7 +169,7 @@ func (p *restartableProcess) getByKindAndName(key kindAndName) (interface{}, err // getByKindAndNameLH returns the dispensed plugin for key. If the plugin hasn't been dispensed before, it dispenses a // new one. -func (p *restartableProcess) getByKindAndNameLH(key kindAndName) (interface{}, error) { +func (p *restartableProcess) getByKindAndNameLH(key KindAndName) (interface{}, error) { dispensed, found := p.plugins[key] if found { return dispensed, nil @@ -184,7 +184,7 @@ func (p *restartableProcess) getByKindAndNameLH(key kindAndName) (interface{}, e } // stop terminates the plugin process. -func (p *restartableProcess) stop() { +func (p *restartableProcess) Stop() { p.lock.Lock() p.process.kill() p.lock.Unlock() diff --git a/pkg/plugin/clientmgmt/restartable_delegate_test.go b/pkg/plugin/clientmgmt/restartable_delegate_test.go index 3e3366c88..c71d3e276 100644 --- a/pkg/plugin/clientmgmt/restartable_delegate_test.go +++ b/pkg/plugin/clientmgmt/restartable_delegate_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" ) @@ -43,7 +44,7 @@ type mockable interface { func runRestartableDelegateTests( t *testing.T, kind framework.PluginKind, - newRestartable func(key kindAndName, p RestartableProcess) interface{}, + newRestartable func(key process.KindAndName, p process.RestartableProcess) interface{}, newMock func() mockable, tests ...restartableDelegateTest, ) { @@ -54,9 +55,9 @@ func runRestartableDelegateTests( defer p.AssertExpectations(t) // getDelegate error - p.On("resetIfNeeded").Return(errors.Errorf("reset error")).Once() + p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "delegateName" - key := kindAndName{kind: kind, name: name} + key := process.KindAndName{Kind: kind, Name: name} r := newRestartable(key, p) // Get the method we're going to call using reflection @@ -107,13 +108,13 @@ func runRestartableDelegateTests( checkOutputs(tc.expectedErrorOutputs, actual) // Invoke delegate, make sure all returned values are passed through - p.On("resetIfNeeded").Return(nil) + p.On("ResetIfNeeded").Return(nil) delegate := newMock() delegate.Test(t) defer delegate.AssertExpectations(t) - p.On("getByKindAndName", key).Return(delegate, nil) + p.On("GetByKindAndName", key).Return(delegate, nil) // Set up the mocked method in the delegate delegate.On(tc.function, tc.inputs...).Return(tc.expectedDelegateOutputs...) diff --git a/pkg/plugin/clientmgmt/restartable_delete_item_action.go b/pkg/plugin/clientmgmt/restartable_delete_item_action.go index 266500c7a..977203aae 100644 --- a/pkg/plugin/clientmgmt/restartable_delete_item_action.go +++ b/pkg/plugin/clientmgmt/restartable_delete_item_action.go @@ -19,6 +19,7 @@ package clientmgmt import ( "github.com/pkg/errors" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -28,15 +29,15 @@ import ( // call, the restartableDeleteItemAction asks its restartableProcess to restart itself if needed (e.g. if the // process terminated for any reason), then it proceeds with the actual call. type restartableDeleteItemAction struct { - key kindAndName - sharedPluginProcess RestartableProcess + key process.KindAndName + sharedPluginProcess process.RestartableProcess config map[string]string } -// newRestartableDeleteItemAction returns a new restartableDeleteItemAction. -func newRestartableDeleteItemAction(name string, sharedPluginProcess RestartableProcess) *restartableDeleteItemAction { +// NewRestartableDeleteItemAction returns a new restartableDeleteItemAction. +func NewRestartableDeleteItemAction(name string, sharedPluginProcess process.RestartableProcess) *restartableDeleteItemAction { r := &restartableDeleteItemAction{ - key: kindAndName{kind: framework.PluginKindDeleteItemAction, name: name}, + key: process.KindAndName{Kind: framework.PluginKindDeleteItemAction, Name: name}, sharedPluginProcess: sharedPluginProcess, } return r @@ -45,7 +46,7 @@ func newRestartableDeleteItemAction(name string, sharedPluginProcess Restartable // getDeleteItemAction returns the delete item action for this restartableDeleteItemAction. It does *not* restart the // plugin process. func (r *restartableDeleteItemAction) getDeleteItemAction() (velero.DeleteItemAction, error) { - plugin, err := r.sharedPluginProcess.getByKindAndName(r.key) + plugin, err := r.sharedPluginProcess.GetByKindAndName(r.key) if err != nil { return nil, err } @@ -60,7 +61,7 @@ func (r *restartableDeleteItemAction) getDeleteItemAction() (velero.DeleteItemAc // getDelegate restarts the plugin process (if needed) and returns the delete item action for this restartableDeleteItemAction. func (r *restartableDeleteItemAction) getDelegate() (velero.DeleteItemAction, error) { - if err := r.sharedPluginProcess.resetIfNeeded(); err != nil { + if err := r.sharedPluginProcess.ResetIfNeeded(); err != nil { return nil, err } diff --git a/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go b/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go index 641959e17..65fb9646c 100644 --- a/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go +++ b/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks" @@ -59,10 +60,10 @@ func TestRestartableGetDeleteItemAction(t *testing.T) { defer p.AssertExpectations(t) name := "pod" - key := kindAndName{kind: framework.PluginKindDeleteItemAction, name: name} - p.On("getByKindAndName", key).Return(tc.plugin, tc.getError) + key := process.KindAndName{Kind: framework.PluginKindDeleteItemAction, Name: name} + p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) - r := newRestartableDeleteItemAction(name, p) + r := NewRestartableDeleteItemAction(name, p) a, err := r.getDeleteItemAction() if tc.expectedError != "" { assert.EqualError(t, err, tc.expectedError) @@ -80,19 +81,19 @@ func TestRestartableDeleteItemActionGetDelegate(t *testing.T) { defer p.AssertExpectations(t) // Reset error - p.On("resetIfNeeded").Return(errors.Errorf("reset error")).Once() + p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "pod" - r := newRestartableDeleteItemAction(name, p) + r := NewRestartableDeleteItemAction(name, p) a, err := r.getDelegate() assert.Nil(t, a) assert.EqualError(t, err, "reset error") // Happy path // Currently broken since this mocks out the restore item action interface - p.On("resetIfNeeded").Return(nil) + p.On("ResetIfNeeded").Return(nil) expected := new(mocks.DeleteItemAction) - key := kindAndName{kind: framework.PluginKindDeleteItemAction, name: name} - p.On("getByKindAndName", key).Return(expected, nil) + key := process.KindAndName{Kind: framework.PluginKindDeleteItemAction, Name: name} + p.On("GetByKindAndName", key).Return(expected, nil) a, err = r.getDelegate() assert.NoError(t, err) @@ -116,7 +117,7 @@ func TestRestartableDeleteItemActionDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, framework.PluginKindDeleteItemAction, - func(key kindAndName, p RestartableProcess) interface{} { + func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableDeleteItemAction{ key: key, sharedPluginProcess: p, diff --git a/pkg/plugin/clientmgmt/restartable_item_snapshotter.go b/pkg/plugin/clientmgmt/restartable_item_snapshotter.go index e211bcf28..d2743789a 100644 --- a/pkg/plugin/clientmgmt/restartable_item_snapshotter.go +++ b/pkg/plugin/clientmgmt/restartable_item_snapshotter.go @@ -21,21 +21,21 @@ import ( "github.com/pkg/errors" - isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1" - + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" + isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1" ) type restartableItemSnapshotter struct { - key kindAndName - sharedPluginProcess RestartableProcess + key process.KindAndName + sharedPluginProcess process.RestartableProcess } -// newRestartableItemSnapshotter returns a new newRestartableItemSnapshotter. -func newRestartableItemSnapshotter(name string, sharedPluginProcess RestartableProcess) *restartableItemSnapshotter { +// NewRestartableItemSnapshotter returns a new restartableItemSnapshotter. +func NewRestartableItemSnapshotter(name string, sharedPluginProcess process.RestartableProcess) *restartableItemSnapshotter { r := &restartableItemSnapshotter{ - key: kindAndName{kind: framework.PluginKindItemSnapshotter, name: name}, + key: process.KindAndName{Kind: framework.PluginKindItemSnapshotter, Name: name}, sharedPluginProcess: sharedPluginProcess, } return r @@ -44,7 +44,7 @@ func newRestartableItemSnapshotter(name string, sharedPluginProcess RestartableP // 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) + plugin, err := r.sharedPluginProcess.GetByKindAndName(r.key) if err != nil { return nil, err } @@ -59,7 +59,7 @@ func (r *restartableItemSnapshotter) getItemSnapshotter() (isv1.ItemSnapshotter, // 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 { + if err := r.sharedPluginProcess.ResetIfNeeded(); err != nil { return nil, err } diff --git a/pkg/plugin/clientmgmt/restartable_item_snapshotter_test.go b/pkg/plugin/clientmgmt/restartable_item_snapshotter_test.go index 30b2aab43..70d4a934a 100644 --- a/pkg/plugin/clientmgmt/restartable_item_snapshotter_test.go +++ b/pkg/plugin/clientmgmt/restartable_item_snapshotter_test.go @@ -21,8 +21,6 @@ import ( "testing" "time" - isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -32,8 +30,10 @@ import ( 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" "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) { @@ -65,10 +65,10 @@ func TestRestartableGetItemSnapshotter(t *testing.T) { defer p.AssertExpectations(t) name := "pvc" - key := kindAndName{kind: framework.PluginKindItemSnapshotter, name: name} - p.On("getByKindAndName", key).Return(tc.plugin, tc.getError) + key := process.KindAndName{Kind: framework.PluginKindItemSnapshotter, Name: name} + p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) - r := newRestartableItemSnapshotter(name, p) + r := NewRestartableItemSnapshotter(name, p) a, err := r.getItemSnapshotter() if tc.expectedError != "" { assert.EqualError(t, err, tc.expectedError) @@ -86,18 +86,18 @@ func TestRestartableItemSnapshotterGetDelegate(t *testing.T) { defer p.AssertExpectations(t) // Reset error - p.On("resetIfNeeded").Return(errors.Errorf("reset error")).Once() + p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "pvc" - r := newRestartableItemSnapshotter(name, p) + 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) + p.On("ResetIfNeeded").Return(nil) expected := new(mocks.ItemSnapshotter) - key := kindAndName{kind: framework.PluginKindItemSnapshotter, name: name} - p.On("getByKindAndName", key).Return(expected, nil) + key := process.KindAndName{Kind: framework.PluginKindItemSnapshotter, Name: name} + p.On("GetByKindAndName", key).Return(expected, nil) a, err = r.getDelegate() assert.NoError(t, err) @@ -178,7 +178,7 @@ func TestRestartableItemSnasphotterDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, framework.PluginKindItemSnapshotter, - func(key kindAndName, p RestartableProcess) interface{} { + func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableItemSnapshotter{ key: key, sharedPluginProcess: p, diff --git a/pkg/plugin/clientmgmt/restartable_object_store.go b/pkg/plugin/clientmgmt/restartable_object_store.go index 95fbc75c5..5be111340 100644 --- a/pkg/plugin/clientmgmt/restartable_object_store.go +++ b/pkg/plugin/clientmgmt/restartable_object_store.go @@ -22,6 +22,7 @@ import ( "github.com/pkg/errors" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -31,29 +32,29 @@ import ( // call, the restartableObjectStore asks its restartableProcess to restart itself if needed (e.g. if the // process terminated for any reason), then it proceeds with the actual call. type restartableObjectStore struct { - key kindAndName - sharedPluginProcess RestartableProcess + key process.KindAndName + sharedPluginProcess process.RestartableProcess // config contains the data used to initialize the plugin. It is used to reinitialize the plugin in the event its // sharedPluginProcess gets restarted. config map[string]string } -// newRestartableObjectStore returns a new restartableObjectStore. -func newRestartableObjectStore(name string, sharedPluginProcess RestartableProcess) *restartableObjectStore { - key := kindAndName{kind: framework.PluginKindObjectStore, name: name} +// NewRestartableObjectStore returns a new restartableObjectStore. +func NewRestartableObjectStore(name string, sharedPluginProcess process.RestartableProcess) *restartableObjectStore { + key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} r := &restartableObjectStore{ key: key, sharedPluginProcess: sharedPluginProcess, } // Register our reinitializer so we can reinitialize after a restart with r.config. - sharedPluginProcess.addReinitializer(key, r) + sharedPluginProcess.AddReinitializer(key, r) return r } // reinitialize reinitializes a re-dispensed plugin using the initial data passed to Init(). -func (r *restartableObjectStore) reinitialize(dispensed interface{}) error { +func (r *restartableObjectStore) Reinitialize(dispensed interface{}) error { objectStore, ok := dispensed.(velero.ObjectStore) if !ok { return errors.Errorf("%T is not a ObjectStore!", dispensed) @@ -65,7 +66,7 @@ func (r *restartableObjectStore) reinitialize(dispensed interface{}) error { // getObjectStore returns the object store for this restartableObjectStore. It does *not* restart the // plugin process. func (r *restartableObjectStore) getObjectStore() (velero.ObjectStore, error) { - plugin, err := r.sharedPluginProcess.getByKindAndName(r.key) + plugin, err := r.sharedPluginProcess.GetByKindAndName(r.key) if err != nil { return nil, err } @@ -80,7 +81,7 @@ func (r *restartableObjectStore) getObjectStore() (velero.ObjectStore, error) { // getDelegate restarts the plugin process (if needed) and returns the object store for this restartableObjectStore. func (r *restartableObjectStore) getDelegate() (velero.ObjectStore, error) { - if err := r.sharedPluginProcess.resetIfNeeded(); err != nil { + if err := r.sharedPluginProcess.ResetIfNeeded(); err != nil { return nil, err } diff --git a/pkg/plugin/clientmgmt/restartable_object_store_test.go b/pkg/plugin/clientmgmt/restartable_object_store_test.go index 57a64e8b2..b4e94fccc 100644 --- a/pkg/plugin/clientmgmt/restartable_object_store_test.go +++ b/pkg/plugin/clientmgmt/restartable_object_store_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" providermocks "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks" ) @@ -60,8 +61,8 @@ func TestRestartableGetObjectStore(t *testing.T) { defer p.AssertExpectations(t) name := "aws" - key := kindAndName{kind: framework.PluginKindObjectStore, name: name} - p.On("getByKindAndName", key).Return(tc.plugin, tc.getError) + key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} + p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) r := &restartableObjectStore{ key: key, @@ -85,7 +86,7 @@ func TestRestartableObjectStoreReinitialize(t *testing.T) { defer p.AssertExpectations(t) name := "aws" - key := kindAndName{kind: framework.PluginKindObjectStore, name: name} + key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} r := &restartableObjectStore{ key: key, sharedPluginProcess: p, @@ -94,7 +95,7 @@ func TestRestartableObjectStoreReinitialize(t *testing.T) { }, } - err := r.reinitialize(3) + err := r.Reinitialize(3) assert.EqualError(t, err, "int is not a ObjectStore!") objectStore := new(providermocks.ObjectStore) @@ -102,11 +103,11 @@ func TestRestartableObjectStoreReinitialize(t *testing.T) { defer objectStore.AssertExpectations(t) objectStore.On("Init", r.config).Return(errors.Errorf("init error")).Once() - err = r.reinitialize(objectStore) + err = r.Reinitialize(objectStore) assert.EqualError(t, err, "init error") objectStore.On("Init", r.config).Return(nil) - err = r.reinitialize(objectStore) + err = r.Reinitialize(objectStore) assert.NoError(t, err) } @@ -116,9 +117,9 @@ func TestRestartableObjectStoreGetDelegate(t *testing.T) { defer p.AssertExpectations(t) // Reset error - p.On("resetIfNeeded").Return(errors.Errorf("reset error")).Once() + p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "aws" - key := kindAndName{kind: framework.PluginKindObjectStore, name: name} + key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} r := &restartableObjectStore{ key: key, sharedPluginProcess: p, @@ -128,11 +129,11 @@ func TestRestartableObjectStoreGetDelegate(t *testing.T) { assert.EqualError(t, err, "reset error") // Happy path - p.On("resetIfNeeded").Return(nil) + p.On("ResetIfNeeded").Return(nil) objectStore := new(providermocks.ObjectStore) objectStore.Test(t) defer objectStore.AssertExpectations(t) - p.On("getByKindAndName", key).Return(objectStore, nil) + p.On("GetByKindAndName", key).Return(objectStore, nil) a, err = r.getDelegate() assert.NoError(t, err) @@ -146,24 +147,24 @@ func TestRestartableObjectStoreInit(t *testing.T) { // getObjectStore error name := "aws" - key := kindAndName{kind: framework.PluginKindObjectStore, name: name} + key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} r := &restartableObjectStore{ key: key, sharedPluginProcess: p, } - p.On("getByKindAndName", key).Return(nil, errors.Errorf("getByKindAndName error")).Once() + p.On("GetByKindAndName", key).Return(nil, errors.Errorf("GetByKindAndName error")).Once() config := map[string]string{ "color": "blue", } err := r.Init(config) - assert.EqualError(t, err, "getByKindAndName error") + assert.EqualError(t, err, "GetByKindAndName error") // Delegate returns error objectStore := new(providermocks.ObjectStore) objectStore.Test(t) defer objectStore.AssertExpectations(t) - p.On("getByKindAndName", key).Return(objectStore, nil) + p.On("GetByKindAndName", key).Return(objectStore, nil) objectStore.On("Init", config).Return(errors.Errorf("Init error")).Once() err = r.Init(config) @@ -187,7 +188,7 @@ func TestRestartableObjectStoreDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, framework.PluginKindObjectStore, - func(key kindAndName, p RestartableProcess) interface{} { + func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableObjectStore{ key: key, sharedPluginProcess: p, diff --git a/pkg/plugin/clientmgmt/restartable_restore_item_action.go b/pkg/plugin/clientmgmt/restartable_restore_item_action.go index 0f55ebfde..c4e6911b4 100644 --- a/pkg/plugin/clientmgmt/restartable_restore_item_action.go +++ b/pkg/plugin/clientmgmt/restartable_restore_item_action.go @@ -19,24 +19,25 @@ package clientmgmt import ( "github.com/pkg/errors" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) -// restartableRestoreItemAction is a restore item action for a given implementation (such as "pod"). It is associated with +// RestartableRestoreItemAction is a restore item action for a given implementation (such as "pod"). It is associated with // a restartableProcess, which may be shared and used to run multiple plugins. At the beginning of each method // call, the restartableRestoreItemAction asks its restartableProcess to restart itself if needed (e.g. if the // process terminated for any reason), then it proceeds with the actual call. type restartableRestoreItemAction struct { - key kindAndName - sharedPluginProcess RestartableProcess + key process.KindAndName + sharedPluginProcess process.RestartableProcess config map[string]string } -// newRestartableRestoreItemAction returns a new restartableRestoreItemAction. -func newRestartableRestoreItemAction(name string, sharedPluginProcess RestartableProcess) *restartableRestoreItemAction { +// NewRestartableRestoreItemAction returns a new RestartableRestoreItemAction. +func NewRestartableRestoreItemAction(name string, sharedPluginProcess process.RestartableProcess) *restartableRestoreItemAction { r := &restartableRestoreItemAction{ - key: kindAndName{kind: framework.PluginKindRestoreItemAction, name: name}, + key: process.KindAndName{Kind: framework.PluginKindRestoreItemAction, Name: name}, sharedPluginProcess: sharedPluginProcess, } return r @@ -45,7 +46,7 @@ func newRestartableRestoreItemAction(name string, sharedPluginProcess Restartabl // getRestoreItemAction returns the restore item action for this restartableRestoreItemAction. It does *not* restart the // plugin process. func (r *restartableRestoreItemAction) getRestoreItemAction() (velero.RestoreItemAction, error) { - plugin, err := r.sharedPluginProcess.getByKindAndName(r.key) + plugin, err := r.sharedPluginProcess.GetByKindAndName(r.key) if err != nil { return nil, err } @@ -60,7 +61,7 @@ func (r *restartableRestoreItemAction) getRestoreItemAction() (velero.RestoreIte // getDelegate restarts the plugin process (if needed) and returns the restore item action for this restartableRestoreItemAction. func (r *restartableRestoreItemAction) getDelegate() (velero.RestoreItemAction, error) { - if err := r.sharedPluginProcess.resetIfNeeded(); err != nil { + if err := r.sharedPluginProcess.ResetIfNeeded(); err != nil { return nil, err } diff --git a/pkg/plugin/clientmgmt/restartable_restore_item_action_test.go b/pkg/plugin/clientmgmt/restartable_restore_item_action_test.go index 8a37cdb4a..3d4fd52e9 100644 --- a/pkg/plugin/clientmgmt/restartable_restore_item_action_test.go +++ b/pkg/plugin/clientmgmt/restartable_restore_item_action_test.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" "github.com/vmware-tanzu/velero/pkg/restore/mocks" @@ -59,10 +60,10 @@ func TestRestartableGetRestoreItemAction(t *testing.T) { defer p.AssertExpectations(t) name := "pod" - key := kindAndName{kind: framework.PluginKindRestoreItemAction, name: name} - p.On("getByKindAndName", key).Return(tc.plugin, tc.getError) + key := process.KindAndName{Kind: framework.PluginKindRestoreItemAction, Name: name} + p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) - r := newRestartableRestoreItemAction(name, p) + r := NewRestartableRestoreItemAction(name, p) a, err := r.getRestoreItemAction() if tc.expectedError != "" { assert.EqualError(t, err, tc.expectedError) @@ -80,18 +81,18 @@ func TestRestartableRestoreItemActionGetDelegate(t *testing.T) { defer p.AssertExpectations(t) // Reset error - p.On("resetIfNeeded").Return(errors.Errorf("reset error")).Once() + p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "pod" - r := newRestartableRestoreItemAction(name, p) + r := NewRestartableRestoreItemAction(name, p) a, err := r.getDelegate() assert.Nil(t, a) assert.EqualError(t, err, "reset error") // Happy path - p.On("resetIfNeeded").Return(nil) + p.On("ResetIfNeeded").Return(nil) expected := new(mocks.ItemAction) - key := kindAndName{kind: framework.PluginKindRestoreItemAction, name: name} - p.On("getByKindAndName", key).Return(expected, nil) + key := process.KindAndName{Kind: framework.PluginKindRestoreItemAction, Name: name} + p.On("GetByKindAndName", key).Return(expected, nil) a, err = r.getDelegate() assert.NoError(t, err) @@ -122,7 +123,7 @@ func TestRestartableRestoreItemActionDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, framework.PluginKindRestoreItemAction, - func(key kindAndName, p RestartableProcess) interface{} { + func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableRestoreItemAction{ key: key, sharedPluginProcess: p, diff --git a/pkg/plugin/clientmgmt/restartable_volume_snapshotter.go b/pkg/plugin/clientmgmt/restartable_volume_snapshotter.go index 5e46bf229..f8a1a66b0 100644 --- a/pkg/plugin/clientmgmt/restartable_volume_snapshotter.go +++ b/pkg/plugin/clientmgmt/restartable_volume_snapshotter.go @@ -20,36 +20,37 @@ import ( "github.com/pkg/errors" "k8s.io/apimachinery/pkg/runtime" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) -// restartableVolumeSnapshotter is a volume snapshotter for a given implementation (such as "aws"). It is associated with +// RestartableVolumeSnapshotter is a volume snapshotter for a given implementation (such as "aws"). It is associated with // a restartableProcess, which may be shared and used to run multiple plugins. At the beginning of each method // call, the restartableVolumeSnapshotter asks its restartableProcess to restart itself if needed (e.g. if the // process terminated for any reason), then it proceeds with the actual call. type restartableVolumeSnapshotter struct { - key kindAndName - sharedPluginProcess RestartableProcess + key process.KindAndName + sharedPluginProcess process.RestartableProcess config map[string]string } -// newRestartableVolumeSnapshotter returns a new restartableVolumeSnapshotter. -func newRestartableVolumeSnapshotter(name string, sharedPluginProcess RestartableProcess) *restartableVolumeSnapshotter { - key := kindAndName{kind: framework.PluginKindVolumeSnapshotter, name: name} +// NewRestartableVolumeSnapshotter returns a new RestartableVolumeSnapshotter. +func NewRestartableVolumeSnapshotter(name string, sharedPluginProcess process.RestartableProcess) *restartableVolumeSnapshotter { + key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} r := &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: sharedPluginProcess, } // Register our reinitializer so we can reinitialize after a restart with r.config. - sharedPluginProcess.addReinitializer(key, r) + sharedPluginProcess.AddReinitializer(key, r) return r } // reinitialize reinitializes a re-dispensed plugin using the initial data passed to Init(). -func (r *restartableVolumeSnapshotter) reinitialize(dispensed interface{}) error { +func (r *restartableVolumeSnapshotter) Reinitialize(dispensed interface{}) error { volumeSnapshotter, ok := dispensed.(velero.VolumeSnapshotter) if !ok { return errors.Errorf("%T is not a VolumeSnapshotter!", dispensed) @@ -60,7 +61,7 @@ func (r *restartableVolumeSnapshotter) reinitialize(dispensed interface{}) error // getVolumeSnapshotter returns the volume snapshotter for this restartableVolumeSnapshotter. It does *not* restart the // plugin process. func (r *restartableVolumeSnapshotter) getVolumeSnapshotter() (velero.VolumeSnapshotter, error) { - plugin, err := r.sharedPluginProcess.getByKindAndName(r.key) + plugin, err := r.sharedPluginProcess.GetByKindAndName(r.key) if err != nil { return nil, err } @@ -75,7 +76,7 @@ func (r *restartableVolumeSnapshotter) getVolumeSnapshotter() (velero.VolumeSnap // getDelegate restarts the plugin process (if needed) and returns the volume snapshotter for this restartableVolumeSnapshotter. func (r *restartableVolumeSnapshotter) getDelegate() (velero.VolumeSnapshotter, error) { - if err := r.sharedPluginProcess.resetIfNeeded(); err != nil { + if err := r.sharedPluginProcess.ResetIfNeeded(); err != nil { return nil, err } diff --git a/pkg/plugin/clientmgmt/restartable_volume_snapshotter_test.go b/pkg/plugin/clientmgmt/restartable_volume_snapshotter_test.go index 762153e05..8d198ec96 100644 --- a/pkg/plugin/clientmgmt/restartable_volume_snapshotter_test.go +++ b/pkg/plugin/clientmgmt/restartable_volume_snapshotter_test.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" providermocks "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks" ) @@ -59,8 +60,8 @@ func TestRestartableGetVolumeSnapshotter(t *testing.T) { defer p.AssertExpectations(t) name := "aws" - key := kindAndName{kind: framework.PluginKindVolumeSnapshotter, name: name} - p.On("getByKindAndName", key).Return(tc.plugin, tc.getError) + key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} + p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) r := &restartableVolumeSnapshotter{ key: key, @@ -84,7 +85,7 @@ func TestRestartableVolumeSnapshotterReinitialize(t *testing.T) { defer p.AssertExpectations(t) name := "aws" - key := kindAndName{kind: framework.PluginKindVolumeSnapshotter, name: name} + key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} r := &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: p, @@ -93,7 +94,7 @@ func TestRestartableVolumeSnapshotterReinitialize(t *testing.T) { }, } - err := r.reinitialize(3) + err := r.Reinitialize(3) assert.EqualError(t, err, "int is not a VolumeSnapshotter!") volumeSnapshotter := new(providermocks.VolumeSnapshotter) @@ -101,11 +102,11 @@ func TestRestartableVolumeSnapshotterReinitialize(t *testing.T) { defer volumeSnapshotter.AssertExpectations(t) volumeSnapshotter.On("Init", r.config).Return(errors.Errorf("init error")).Once() - err = r.reinitialize(volumeSnapshotter) + err = r.Reinitialize(volumeSnapshotter) assert.EqualError(t, err, "init error") volumeSnapshotter.On("Init", r.config).Return(nil) - err = r.reinitialize(volumeSnapshotter) + err = r.Reinitialize(volumeSnapshotter) assert.NoError(t, err) } @@ -115,9 +116,9 @@ func TestRestartableVolumeSnapshotterGetDelegate(t *testing.T) { defer p.AssertExpectations(t) // Reset error - p.On("resetIfNeeded").Return(errors.Errorf("reset error")).Once() + p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "aws" - key := kindAndName{kind: framework.PluginKindVolumeSnapshotter, name: name} + key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} r := &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: p, @@ -127,11 +128,11 @@ func TestRestartableVolumeSnapshotterGetDelegate(t *testing.T) { assert.EqualError(t, err, "reset error") // Happy path - p.On("resetIfNeeded").Return(nil) + p.On("ResetIfNeeded").Return(nil) volumeSnapshotter := new(providermocks.VolumeSnapshotter) volumeSnapshotter.Test(t) defer volumeSnapshotter.AssertExpectations(t) - p.On("getByKindAndName", key).Return(volumeSnapshotter, nil) + p.On("GetByKindAndName", key).Return(volumeSnapshotter, nil) a, err = r.getDelegate() assert.NoError(t, err) @@ -145,24 +146,24 @@ func TestRestartableVolumeSnapshotterInit(t *testing.T) { // getVolumeSnapshottererror name := "aws" - key := kindAndName{kind: framework.PluginKindVolumeSnapshotter, name: name} + key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} r := &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: p, } - p.On("getByKindAndName", key).Return(nil, errors.Errorf("getByKindAndName error")).Once() + p.On("GetByKindAndName", key).Return(nil, errors.Errorf("GetByKindAndName error")).Once() config := map[string]string{ "color": "blue", } err := r.Init(config) - assert.EqualError(t, err, "getByKindAndName error") + assert.EqualError(t, err, "GetByKindAndName error") // Delegate returns error volumeSnapshotter := new(providermocks.VolumeSnapshotter) volumeSnapshotter.Test(t) defer volumeSnapshotter.AssertExpectations(t) - p.On("getByKindAndName", key).Return(volumeSnapshotter, nil) + p.On("GetByKindAndName", key).Return(volumeSnapshotter, nil) volumeSnapshotter.On("Init", config).Return(errors.Errorf("Init error")).Once() err = r.Init(config) @@ -198,7 +199,7 @@ func TestRestartableVolumeSnapshotterDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, framework.PluginKindVolumeSnapshotter, - func(key kindAndName, p RestartableProcess) interface{} { + func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: p, diff --git a/pkg/plugin/mocks/process_factory.go b/pkg/plugin/mocks/process_factory.go index 22abc81fc..586e31121 100644 --- a/pkg/plugin/mocks/process_factory.go +++ b/pkg/plugin/mocks/process_factory.go @@ -1,5 +1,5 @@ /* -Copyright 2018 the Velero contributors. +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. @@ -14,11 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ // Code generated by mockery v1.0.0. DO NOT EDIT. + package mocks -import logrus "github.com/sirupsen/logrus" -import mock "github.com/stretchr/testify/mock" -import "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt" +import ( + logrus "github.com/sirupsen/logrus" + mock "github.com/stretchr/testify/mock" + + process "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" +) // ProcessFactory is an autogenerated mock type for the ProcessFactory type type ProcessFactory struct { @@ -26,15 +30,15 @@ type ProcessFactory struct { } // newProcess provides a mock function with given fields: command, logger, logLevel -func (_m *ProcessFactory) newProcess(command string, logger logrus.FieldLogger, logLevel logrus.Level) (clientmgmt.Process, error) { +func (_m *ProcessFactory) newProcess(command string, logger logrus.FieldLogger, logLevel logrus.Level) (process.Process, error) { ret := _m.Called(command, logger, logLevel) - var r0 clientmgmt.Process - if rf, ok := ret.Get(0).(func(string, logrus.FieldLogger, logrus.Level) clientmgmt.Process); ok { + var r0 process.Process + if rf, ok := ret.Get(0).(func(string, logrus.FieldLogger, logrus.Level) process.Process); ok { r0 = rf(command, logger, logLevel) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(clientmgmt.Process) + r0 = ret.Get(0).(process.Process) } } From e3e2a8dfa03fdd83c0acdcb490901a370b92659e Mon Sep 17 00:00:00 2001 From: Scott Seago Date: Thu, 1 Sep 2022 14:30:07 -0400 Subject: [PATCH 2/2] plugin/framework refactoring for BackupItemAction v1 Refactors the framework package to implement the plugin versioning changes needed for BIA v1 and overall package refactoring to support plugin versions in different packages. This should be all that's needed to move on to v2 for BackupItemAction. The remaining plugin types still need similar refactoring to what's being done here for BIA before attempting a v2 implementation. Signed-off-by: Scott Seago --- internal/delete/delete_item_action_handler.go | 2 +- internal/velero/serverstatusrequest.go | 5 +- pkg/backup/backup.go | 4 +- pkg/cmd/server/plugin/plugin.go | 11 +- .../server_status_request_controller.go | 3 +- .../server_status_request_controller_test.go | 3 +- .../v1/restartable_backup_item_action.go | 8 +- .../v1/restartable_backup_item_action_test.go | 16 +-- .../backupitemaction/v1/shared_test.go | 4 +- pkg/plugin/clientmgmt/manager.go | 27 +++-- pkg/plugin/clientmgmt/manager_test.go | 35 +++--- .../clientmgmt/process/client_builder.go | 15 +-- .../clientmgmt/process/client_builder_test.go | 15 +-- pkg/plugin/clientmgmt/process/process.go | 4 +- pkg/plugin/clientmgmt/process/process_test.go | 5 +- pkg/plugin/clientmgmt/process/registry.go | 32 ++++-- .../clientmgmt/restartable_delegate_test.go | 4 +- .../restartable_delete_item_action.go | 4 +- .../restartable_delete_item_action_test.go | 8 +- .../restartable_item_snapshotter.go | 4 +- .../restartable_item_snapshotter_test.go | 8 +- .../clientmgmt/restartable_object_store.go | 4 +- .../restartable_object_store_test.go | 12 +- .../restartable_restore_item_action.go | 4 +- .../restartable_restore_item_action_test.go | 8 +- .../restartable_volume_snapshotter.go | 6 +- .../restartable_volume_snapshotter_test.go | 12 +- pkg/plugin/framework/action_resolver.go | 10 +- pkg/plugin/framework/backup_item_action.go | 7 +- .../framework/backup_item_action_client.go | 19 ++-- .../framework/backup_item_action_server.go | 23 ++-- .../framework/backup_item_action_test.go | 11 +- .../{ => common}/client_dispenser.go | 20 ++-- .../{ => common}/client_dispenser_test.go | 18 +-- .../framework/{ => common}/client_errors.go | 16 +-- .../framework/{ => common}/handle_panic.go | 10 +- .../framework/{ => common}/plugin_base.go | 24 ++-- .../{ => common}/plugin_base_test.go | 12 +- .../framework/{ => common}/plugin_kinds.go | 7 +- .../framework/{ => common}/server_errors.go | 22 ++-- .../framework/{ => common}/server_mux.go | 40 +++---- .../framework/{ => common}/server_mux_test.go | 2 +- pkg/plugin/framework/delete_item_action.go | 7 +- .../framework/delete_item_action_client.go | 19 ++-- .../framework/delete_item_action_server.go | 21 ++-- pkg/plugin/framework/interface.go | 2 +- pkg/plugin/framework/item_snapshotter.go | 7 +- .../framework/item_snapshotter_client.go | 27 ++--- .../framework/item_snapshotter_server.go | 67 ++++++------ pkg/plugin/framework/object_store.go | 7 +- pkg/plugin/framework/object_store_client.go | 49 +++++---- pkg/plugin/framework/object_store_server.go | 61 ++++++----- pkg/plugin/framework/plugin_lister.go | 9 +- pkg/plugin/framework/restore_item_action.go | 7 +- .../framework/restore_item_action_client.go | 19 ++-- .../framework/restore_item_action_server.go | 25 +++-- pkg/plugin/framework/server.go | 103 +++++++++--------- pkg/plugin/framework/volume_snapshotter.go | 7 +- .../framework/volume_snapshotter_client.go | 39 +++---- .../framework/volume_snapshotter_server.go | 53 ++++----- .../backupitemaction/v1/BackupItemAction.go} | 34 +++--- pkg/restore/change_pvc_node_selector.go | 4 +- pkg/restore/change_storageclass_action.go | 4 +- pkg/restore/restic_restore_action.go | 6 +- pkg/restore/restore.go | 4 +- 65 files changed, 567 insertions(+), 518 deletions(-) rename pkg/plugin/framework/{ => common}/client_dispenser.go (86%) rename pkg/plugin/framework/{ => common}/client_dispenser_test.go (83%) rename pkg/plugin/framework/{ => common}/client_errors.go (84%) rename pkg/plugin/framework/{ => common}/handle_panic.go (84%) rename pkg/plugin/framework/{ => common}/plugin_base.go (65%) rename pkg/plugin/framework/{ => common}/plugin_base_test.go (84%) rename pkg/plugin/framework/{ => common}/plugin_kinds.go (89%) rename pkg/plugin/framework/{ => common}/server_errors.go (78%) rename pkg/plugin/framework/{ => common}/server_mux.go (78%) rename pkg/plugin/framework/{ => common}/server_mux_test.go (99%) rename pkg/{backup/mocks/item_action.go => plugin/velero/mocks/backupitemaction/v1/BackupItemAction.go} (58%) diff --git a/internal/delete/delete_item_action_handler.go b/internal/delete/delete_item_action_handler.go index b08c8e024..bdcf511b2 100644 --- a/internal/delete/delete_item_action_handler.go +++ b/internal/delete/delete_item_action_handler.go @@ -48,7 +48,7 @@ type Context struct { func InvokeDeleteActions(ctx *Context) error { var err error resolver := framework.NewDeleteItemActionResolver(ctx.Actions) - ctx.resolvedActions, err = resolver.ResolveActions(ctx.DiscoveryHelper) + ctx.resolvedActions, err = resolver.ResolveActions(ctx.DiscoveryHelper, ctx.Log) // No actions installed and no error means we don't have to continue; // just do the backup deletion without worrying about plugins. if len(ctx.resolvedActions) == 0 && err == nil { diff --git a/internal/velero/serverstatusrequest.go b/internal/velero/serverstatusrequest.go index a220c5c19..c9c8acc0a 100644 --- a/internal/velero/serverstatusrequest.go +++ b/internal/velero/serverstatusrequest.go @@ -19,17 +19,18 @@ package velero import ( velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" ) type PluginLister interface { // List returns all PluginIdentifiers for kind. - List(kind framework.PluginKind) []framework.PluginIdentifier + List(kind common.PluginKind) []framework.PluginIdentifier } // GetInstalledPluginInfo returns a list of installed plugins func GetInstalledPluginInfo(pluginLister PluginLister) []velerov1api.PluginInfo { var plugins []velerov1api.PluginInfo - for _, v := range framework.AllPluginKinds() { + for _, v := range common.AllPluginKinds() { list := pluginLister.List(v) for _, plugin := range list { pluginInfo := velerov1api.PluginInfo{ diff --git a/pkg/backup/backup.go b/pkg/backup/backup.go index 771ee5ee1..2843cb54b 100644 --- a/pkg/backup/backup.go +++ b/pkg/backup/backup.go @@ -214,13 +214,13 @@ func (kb *kubernetesBackupper) BackupWithResolvers(log logrus.FieldLogger, return err } - backupRequest.ResolvedActions, err = backupItemActionResolver.ResolveActions(kb.discoveryHelper) + backupRequest.ResolvedActions, err = backupItemActionResolver.ResolveActions(kb.discoveryHelper, log) if err != nil { log.WithError(errors.WithStack(err)).Debugf("Error from backupItemActionResolver.ResolveActions") return err } - backupRequest.ResolvedItemSnapshotters, err = itemSnapshotterResolver.ResolveActions(kb.discoveryHelper) + backupRequest.ResolvedItemSnapshotters, err = itemSnapshotterResolver.ResolveActions(kb.discoveryHelper, log) if err != nil { log.WithError(errors.WithStack(err)).Debugf("Error from itemSnapshotterResolver.ResolveActions") return err diff --git a/pkg/cmd/server/plugin/plugin.go b/pkg/cmd/server/plugin/plugin.go index 5dec03856..64dbe4572 100644 --- a/pkg/cmd/server/plugin/plugin.go +++ b/pkg/cmd/server/plugin/plugin.go @@ -28,6 +28,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/client" velerodiscovery "github.com/vmware-tanzu/velero/pkg/discovery" veleroplugin "github.com/vmware-tanzu/velero/pkg/plugin/framework" + plugincommon "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/restore" ) @@ -76,7 +77,7 @@ func newPodBackupItemAction(logger logrus.FieldLogger) (interface{}, error) { return backup.NewPodAction(logger), nil } -func newServiceAccountBackupItemAction(f client.Factory) veleroplugin.HandlerInitializer { +func newServiceAccountBackupItemAction(f client.Factory) plugincommon.HandlerInitializer { return func(logger logrus.FieldLogger) (interface{}, error) { // TODO(ncdc): consider a k8s style WantsKubernetesClientSet initialization approach clientset, err := f.KubeClient() @@ -101,7 +102,7 @@ func newServiceAccountBackupItemAction(f client.Factory) veleroplugin.HandlerIni } } -func newRemapCRDVersionAction(f client.Factory) veleroplugin.HandlerInitializer { +func newRemapCRDVersionAction(f client.Factory) plugincommon.HandlerInitializer { return func(logger logrus.FieldLogger) (interface{}, error) { config, err := f.ClientConfig() if err != nil { @@ -138,7 +139,7 @@ func newInitRestoreHookPodAction(logger logrus.FieldLogger) (interface{}, error) return restore.NewInitRestoreHookPodAction(logger), nil } -func newResticRestoreItemAction(f client.Factory) veleroplugin.HandlerInitializer { +func newResticRestoreItemAction(f client.Factory) plugincommon.HandlerInitializer { return func(logger logrus.FieldLogger) (interface{}, error) { client, err := f.KubeClient() if err != nil { @@ -174,7 +175,7 @@ func newCRDV1PreserveUnknownFieldsItemAction(logger logrus.FieldLogger) (interfa return restore.NewCRDV1PreserveUnknownFieldsAction(logger), nil } -func newChangeStorageClassRestoreItemAction(f client.Factory) veleroplugin.HandlerInitializer { +func newChangeStorageClassRestoreItemAction(f client.Factory) plugincommon.HandlerInitializer { return func(logger logrus.FieldLogger) (interface{}, error) { client, err := f.KubeClient() if err != nil { @@ -197,7 +198,7 @@ func newClusterRoleBindingItemAction(logger logrus.FieldLogger) (interface{}, er return restore.NewClusterRoleBindingAction(logger), nil } -func newChangePVCNodeSelectorItemAction(f client.Factory) veleroplugin.HandlerInitializer { +func newChangePVCNodeSelectorItemAction(f client.Factory) plugincommon.HandlerInitializer { return func(logger logrus.FieldLogger) (interface{}, error) { client, err := f.KubeClient() if err != nil { diff --git a/pkg/controller/server_status_request_controller.go b/pkg/controller/server_status_request_controller.go index 6d7657683..50ae60627 100644 --- a/pkg/controller/server_status_request_controller.go +++ b/pkg/controller/server_status_request_controller.go @@ -33,6 +33,7 @@ import ( velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/buildinfo" "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" ) const ( @@ -42,7 +43,7 @@ const ( type PluginLister interface { // List returns all PluginIdentifiers for kind. - List(kind framework.PluginKind) []framework.PluginIdentifier + List(kind common.PluginKind) []framework.PluginIdentifier } // serverStatusRequestReconciler reconciles a ServerStatusRequest object diff --git a/pkg/controller/server_status_request_controller_test.go b/pkg/controller/server_status_request_controller_test.go index c968a6018..f86ed4952 100644 --- a/pkg/controller/server_status_request_controller_test.go +++ b/pkg/controller/server_status_request_controller_test.go @@ -36,6 +36,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/builder" "github.com/vmware-tanzu/velero/pkg/buildinfo" "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" velerotest "github.com/vmware-tanzu/velero/pkg/test" ) @@ -247,7 +248,7 @@ type fakePluginLister struct { plugins []framework.PluginIdentifier } -func (l *fakePluginLister) List(kind framework.PluginKind) []framework.PluginIdentifier { +func (l *fakePluginLister) List(kind common.PluginKind) []framework.PluginIdentifier { var plugins []framework.PluginIdentifier for _, plugin := range l.plugins { if plugin.Kind == kind { diff --git a/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action.go b/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action.go index 3317be280..6cbca3f52 100644 --- a/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action.go +++ b/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action.go @@ -22,14 +22,14 @@ import ( api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" biav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v1" ) // AdaptedBackupItemAction is a backup item action adapted to the v1 BackupItemAction API type AdaptedBackupItemAction struct { - Kind framework.PluginKind + Kind common.PluginKind // Get returns a restartable BackupItemAction for the given name and process, wrapping if necessary GetRestartable func(name string, restartableProcess process.RestartableProcess) biav1.BackupItemAction @@ -38,7 +38,7 @@ type AdaptedBackupItemAction struct { func AdaptedBackupItemActions() []AdaptedBackupItemAction { return []AdaptedBackupItemAction{ { - Kind: framework.PluginKindBackupItemAction, + Kind: common.PluginKindBackupItemAction, GetRestartable: func(name string, restartableProcess process.RestartableProcess) biav1.BackupItemAction { return NewRestartableBackupItemAction(name, restartableProcess) }, @@ -58,7 +58,7 @@ type RestartableBackupItemAction struct { // NewRestartableBackupItemAction returns a new RestartableBackupItemAction. func NewRestartableBackupItemAction(name string, sharedPluginProcess process.RestartableProcess) *RestartableBackupItemAction { r := &RestartableBackupItemAction{ - Key: process.KindAndName{Kind: framework.PluginKindBackupItemAction, Name: name}, + Key: process.KindAndName{Kind: common.PluginKindBackupItemAction, Name: name}, SharedPluginProcess: sharedPluginProcess, } return r diff --git a/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action_test.go b/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action_test.go index 947a0f150..d20b150d9 100644 --- a/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action_test.go +++ b/pkg/plugin/clientmgmt/backupitemaction/v1/restartable_backup_item_action_test.go @@ -26,10 +26,10 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - "github.com/vmware-tanzu/velero/pkg/backup/mocks" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" + mocks "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks/backupitemaction/v1" ) func TestRestartableGetBackupItemAction(t *testing.T) { @@ -51,7 +51,7 @@ func TestRestartableGetBackupItemAction(t *testing.T) { }, { name: "happy path", - plugin: new(mocks.ItemAction), + plugin: new(mocks.BackupItemAction), }, } @@ -61,7 +61,7 @@ func TestRestartableGetBackupItemAction(t *testing.T) { defer p.AssertExpectations(t) name := "pod" - key := process.KindAndName{Kind: framework.PluginKindBackupItemAction, Name: name} + key := process.KindAndName{Kind: common.PluginKindBackupItemAction, Name: name} p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) r := NewRestartableBackupItemAction(name, p) @@ -91,8 +91,8 @@ func TestRestartableBackupItemActionGetDelegate(t *testing.T) { // Happy path p.On("ResetIfNeeded").Return(nil) - expected := new(mocks.ItemAction) - key := process.KindAndName{Kind: framework.PluginKindBackupItemAction, Name: name} + expected := new(mocks.BackupItemAction) + key := process.KindAndName{Kind: common.PluginKindBackupItemAction, Name: name} p.On("GetByKindAndName", key).Return(expected, nil) a, err = r.getDelegate() @@ -123,7 +123,7 @@ func TestRestartableBackupItemActionDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, - framework.PluginKindBackupItemAction, + common.PluginKindBackupItemAction, func(key process.KindAndName, p process.RestartableProcess) interface{} { return &RestartableBackupItemAction{ Key: key, @@ -131,7 +131,7 @@ func TestRestartableBackupItemActionDelegatedFunctions(t *testing.T) { } }, func() mockable { - return new(mocks.ItemAction) + return new(mocks.BackupItemAction) }, restartableDelegateTest{ function: "AppliesTo", diff --git a/pkg/plugin/clientmgmt/backupitemaction/v1/shared_test.go b/pkg/plugin/clientmgmt/backupitemaction/v1/shared_test.go index a612c764c..6745b8fa0 100644 --- a/pkg/plugin/clientmgmt/backupitemaction/v1/shared_test.go +++ b/pkg/plugin/clientmgmt/backupitemaction/v1/shared_test.go @@ -25,7 +25,7 @@ import ( "github.com/stretchr/testify/require" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" ) type mockRestartableProcess struct { @@ -70,7 +70,7 @@ type mockable interface { func runRestartableDelegateTests( t *testing.T, - kind framework.PluginKind, + kind common.PluginKind, newRestartable func(key process.KindAndName, p process.RestartableProcess) interface{}, newMock func() mockable, tests ...restartableDelegateTest, diff --git a/pkg/plugin/clientmgmt/manager.go b/pkg/plugin/clientmgmt/manager.go index e2b55951c..292e8e9c2 100644 --- a/pkg/plugin/clientmgmt/manager.go +++ b/pkg/plugin/clientmgmt/manager.go @@ -26,7 +26,7 @@ import ( biav1cli "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/backupitemaction/v1" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" biav1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v1" isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1" @@ -68,6 +68,9 @@ type Manager interface { CleanupClients() } +// Used checking for adapted plugin versions +var pluginNotFoundErrType = &process.PluginNotFoundError{} + // manager implements Manager. type manager struct { logger logrus.FieldLogger @@ -106,7 +109,7 @@ func (m *manager) CleanupClients() { // getRestartableProcess returns a restartableProcess for a plugin identified by kind and name, creating a // restartableProcess if it is the first time it has been requested. -func (m *manager) getRestartableProcess(kind framework.PluginKind, name string) (process.RestartableProcess, error) { +func (m *manager) getRestartableProcess(kind common.PluginKind, name string) (process.RestartableProcess, error) { m.lock.Lock() defer m.lock.Unlock() @@ -145,7 +148,7 @@ func (m *manager) getRestartableProcess(kind framework.PluginKind, name string) func (m *manager) GetObjectStore(name string) (velero.ObjectStore, error) { name = sanitizeName(name) - restartableProcess, err := m.getRestartableProcess(framework.PluginKindObjectStore, name) + restartableProcess, err := m.getRestartableProcess(common.PluginKindObjectStore, name) if err != nil { return nil, err } @@ -159,7 +162,7 @@ func (m *manager) GetObjectStore(name string) (velero.ObjectStore, error) { func (m *manager) GetVolumeSnapshotter(name string) (velero.VolumeSnapshotter, error) { name = sanitizeName(name) - restartableProcess, err := m.getRestartableProcess(framework.PluginKindVolumeSnapshotter, name) + restartableProcess, err := m.getRestartableProcess(common.PluginKindVolumeSnapshotter, name) if err != nil { return nil, err } @@ -171,7 +174,7 @@ func (m *manager) GetVolumeSnapshotter(name string) (velero.VolumeSnapshotter, e // GetBackupItemActions returns all backup item actions as restartableBackupItemActions. func (m *manager) GetBackupItemActions() ([]biav1.BackupItemAction, error) { - list := m.registry.List(framework.PluginKindBackupItemAction) + list := m.registry.List(common.PluginKindBackupItemAction) actions := make([]biav1.BackupItemAction, 0, len(list)) @@ -196,7 +199,7 @@ func (m *manager) GetBackupItemAction(name string) (biav1.BackupItemAction, erro for _, adaptedBackupItemAction := range biav1cli.AdaptedBackupItemActions() { restartableProcess, err := m.getRestartableProcess(adaptedBackupItemAction.Kind, name) // Check if plugin was not found - if errors.Is(err, &process.PluginNotFoundError{}) { + if errors.As(err, &pluginNotFoundErrType) { continue } if err != nil { @@ -209,7 +212,7 @@ func (m *manager) GetBackupItemAction(name string) (biav1.BackupItemAction, erro // GetRestoreItemActions returns all restore item actions as restartableRestoreItemActions. func (m *manager) GetRestoreItemActions() ([]velero.RestoreItemAction, error) { - list := m.registry.List(framework.PluginKindRestoreItemAction) + list := m.registry.List(common.PluginKindRestoreItemAction) actions := make([]velero.RestoreItemAction, 0, len(list)) @@ -231,7 +234,7 @@ func (m *manager) GetRestoreItemActions() ([]velero.RestoreItemAction, error) { func (m *manager) GetRestoreItemAction(name string) (velero.RestoreItemAction, error) { name = sanitizeName(name) - restartableProcess, err := m.getRestartableProcess(framework.PluginKindRestoreItemAction, name) + restartableProcess, err := m.getRestartableProcess(common.PluginKindRestoreItemAction, name) if err != nil { return nil, err } @@ -242,7 +245,7 @@ func (m *manager) GetRestoreItemAction(name string) (velero.RestoreItemAction, e // GetDeleteItemActions returns all delete item actions as restartableDeleteItemActions. func (m *manager) GetDeleteItemActions() ([]velero.DeleteItemAction, error) { - list := m.registry.List(framework.PluginKindDeleteItemAction) + list := m.registry.List(common.PluginKindDeleteItemAction) actions := make([]velero.DeleteItemAction, 0, len(list)) @@ -264,7 +267,7 @@ func (m *manager) GetDeleteItemActions() ([]velero.DeleteItemAction, error) { func (m *manager) GetDeleteItemAction(name string) (velero.DeleteItemAction, error) { name = sanitizeName(name) - restartableProcess, err := m.getRestartableProcess(framework.PluginKindDeleteItemAction, name) + restartableProcess, err := m.getRestartableProcess(common.PluginKindDeleteItemAction, name) if err != nil { return nil, err } @@ -276,7 +279,7 @@ func (m *manager) GetDeleteItemAction(name string) (velero.DeleteItemAction, err func (m *manager) GetItemSnapshotter(name string) (isv1.ItemSnapshotter, error) { name = sanitizeName(name) - restartableProcess, err := m.getRestartableProcess(framework.PluginKindItemSnapshotter, name) + restartableProcess, err := m.getRestartableProcess(common.PluginKindItemSnapshotter, name) if err != nil { return nil, err } @@ -286,7 +289,7 @@ func (m *manager) GetItemSnapshotter(name string) (isv1.ItemSnapshotter, error) } func (m *manager) GetItemSnapshotters() ([]isv1.ItemSnapshotter, error) { - list := m.registry.List(framework.PluginKindItemSnapshotter) + list := m.registry.List(common.PluginKindItemSnapshotter) actions := make([]isv1.ItemSnapshotter, 0, len(list)) diff --git a/pkg/plugin/clientmgmt/manager_test.go b/pkg/plugin/clientmgmt/manager_test.go index 64b8bf4ed..b5b54b3f4 100644 --- a/pkg/plugin/clientmgmt/manager_test.go +++ b/pkg/plugin/clientmgmt/manager_test.go @@ -29,6 +29,7 @@ import ( biav1cli "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/backupitemaction/v1" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/test" ) @@ -41,12 +42,12 @@ func (r *mockRegistry) DiscoverPlugins() error { return args.Error(0) } -func (r *mockRegistry) List(kind framework.PluginKind) []framework.PluginIdentifier { +func (r *mockRegistry) List(kind common.PluginKind) []framework.PluginIdentifier { args := r.Called(kind) return args.Get(0).([]framework.PluginIdentifier) } -func (r *mockRegistry) Get(kind framework.PluginKind, name string) (framework.PluginIdentifier, error) { +func (r *mockRegistry) Get(kind common.PluginKind, name string) (framework.PluginIdentifier, error) { args := r.Called(kind, name) var id framework.PluginIdentifier if args.Get(0) != nil { @@ -123,7 +124,7 @@ func TestGetRestartableProcess(t *testing.T) { m.restartableProcessFactory = factory // Test 1: registry error - pluginKind := framework.PluginKindBackupItemAction + pluginKind := common.PluginKindBackupItemAction pluginName := "pod" registry.On("Get", pluginKind, pluginName).Return(nil, errors.Errorf("registry")).Once() rp, err := m.getRestartableProcess(pluginKind, pluginName) @@ -177,14 +178,14 @@ func TestCleanupClients(t *testing.T) { func TestGetObjectStore(t *testing.T) { getPluginTest(t, - framework.PluginKindObjectStore, + common.PluginKindObjectStore, "velero.io/aws", func(m Manager, name string) (interface{}, error) { return m.GetObjectStore(name) }, func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &restartableObjectStore{ - key: process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name}, + key: process.KindAndName{Kind: common.PluginKindObjectStore, Name: name}, sharedPluginProcess: sharedPluginProcess, } }, @@ -194,14 +195,14 @@ func TestGetObjectStore(t *testing.T) { func TestGetVolumeSnapshotter(t *testing.T) { getPluginTest(t, - framework.PluginKindVolumeSnapshotter, + common.PluginKindVolumeSnapshotter, "velero.io/aws", func(m Manager, name string) (interface{}, error) { return m.GetVolumeSnapshotter(name) }, func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &restartableVolumeSnapshotter{ - key: process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name}, + key: process.KindAndName{Kind: common.PluginKindVolumeSnapshotter, Name: name}, sharedPluginProcess: sharedPluginProcess, } }, @@ -211,14 +212,14 @@ func TestGetVolumeSnapshotter(t *testing.T) { func TestGetBackupItemAction(t *testing.T) { getPluginTest(t, - framework.PluginKindBackupItemAction, + common.PluginKindBackupItemAction, "velero.io/pod", func(m Manager, name string) (interface{}, error) { return m.GetBackupItemAction(name) }, func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &biav1cli.RestartableBackupItemAction{ - Key: process.KindAndName{Kind: framework.PluginKindBackupItemAction, Name: name}, + Key: process.KindAndName{Kind: common.PluginKindBackupItemAction, Name: name}, SharedPluginProcess: sharedPluginProcess, } }, @@ -228,14 +229,14 @@ func TestGetBackupItemAction(t *testing.T) { func TestGetRestoreItemAction(t *testing.T) { getPluginTest(t, - framework.PluginKindRestoreItemAction, + common.PluginKindRestoreItemAction, "velero.io/pod", func(m Manager, name string) (interface{}, error) { return m.GetRestoreItemAction(name) }, func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &restartableRestoreItemAction{ - key: process.KindAndName{Kind: framework.PluginKindRestoreItemAction, Name: name}, + key: process.KindAndName{Kind: common.PluginKindRestoreItemAction, Name: name}, sharedPluginProcess: sharedPluginProcess, } }, @@ -245,7 +246,7 @@ func TestGetRestoreItemAction(t *testing.T) { func getPluginTest( t *testing.T, - kind framework.PluginKind, + kind common.PluginKind, name string, getPluginFunc func(m Manager, name string) (interface{}, error), expectedResultFunc func(name string, sharedPluginProcess process.RestartableProcess) interface{}, @@ -329,7 +330,7 @@ func TestGetBackupItemActions(t *testing.T) { defer factory.AssertExpectations(t) m.restartableProcessFactory = factory - pluginKind := framework.PluginKindBackupItemAction + pluginKind := common.PluginKindBackupItemAction var pluginIDs []framework.PluginIdentifier for i := range tc.names { pluginID := framework.PluginIdentifier{ @@ -421,7 +422,7 @@ func TestGetRestoreItemActions(t *testing.T) { defer factory.AssertExpectations(t) m.restartableProcessFactory = factory - pluginKind := framework.PluginKindRestoreItemAction + pluginKind := common.PluginKindRestoreItemAction var pluginIDs []framework.PluginIdentifier for i := range tc.names { pluginID := framework.PluginIdentifier{ @@ -480,14 +481,14 @@ func TestGetRestoreItemActions(t *testing.T) { func TestGetDeleteItemAction(t *testing.T) { getPluginTest(t, - framework.PluginKindDeleteItemAction, + common.PluginKindDeleteItemAction, "velero.io/deleter", func(m Manager, name string) (interface{}, error) { return m.GetDeleteItemAction(name) }, func(name string, sharedPluginProcess process.RestartableProcess) interface{} { return &restartableDeleteItemAction{ - key: process.KindAndName{Kind: framework.PluginKindDeleteItemAction, Name: name}, + key: process.KindAndName{Kind: common.PluginKindDeleteItemAction, Name: name}, sharedPluginProcess: sharedPluginProcess, } }, @@ -520,7 +521,7 @@ func TestGetDeleteItemActions(t *testing.T) { defer factory.AssertExpectations(t) m.restartableProcessFactory = factory - pluginKind := framework.PluginKindDeleteItemAction + pluginKind := common.PluginKindDeleteItemAction var pluginIDs []framework.PluginIdentifier for i := range tc.names { pluginID := framework.PluginIdentifier{ diff --git a/pkg/plugin/clientmgmt/process/client_builder.go b/pkg/plugin/clientmgmt/process/client_builder.go index 0d3948807..4b6c27731 100644 --- a/pkg/plugin/clientmgmt/process/client_builder.go +++ b/pkg/plugin/clientmgmt/process/client_builder.go @@ -27,6 +27,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/features" "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" ) // clientBuilder builds go-plugin Clients. @@ -67,13 +68,13 @@ func (b *clientBuilder) clientConfig() *hcplugin.ClientConfig { HandshakeConfig: framework.Handshake(), AllowedProtocols: []hcplugin.Protocol{hcplugin.ProtocolGRPC}, Plugins: map[string]hcplugin.Plugin{ - string(framework.PluginKindBackupItemAction): framework.NewBackupItemActionPlugin(framework.ClientLogger(b.clientLogger)), - string(framework.PluginKindVolumeSnapshotter): framework.NewVolumeSnapshotterPlugin(framework.ClientLogger(b.clientLogger)), - string(framework.PluginKindObjectStore): framework.NewObjectStorePlugin(framework.ClientLogger(b.clientLogger)), - string(framework.PluginKindPluginLister): &framework.PluginListerPlugin{}, - string(framework.PluginKindRestoreItemAction): framework.NewRestoreItemActionPlugin(framework.ClientLogger(b.clientLogger)), - string(framework.PluginKindDeleteItemAction): framework.NewDeleteItemActionPlugin(framework.ClientLogger(b.clientLogger)), - string(framework.PluginKindItemSnapshotter): framework.NewItemSnapshotterPlugin(framework.ClientLogger(b.clientLogger)), + string(common.PluginKindBackupItemAction): framework.NewBackupItemActionPlugin(common.ClientLogger(b.clientLogger)), + string(common.PluginKindVolumeSnapshotter): framework.NewVolumeSnapshotterPlugin(common.ClientLogger(b.clientLogger)), + string(common.PluginKindObjectStore): framework.NewObjectStorePlugin(common.ClientLogger(b.clientLogger)), + string(common.PluginKindPluginLister): &framework.PluginListerPlugin{}, + string(common.PluginKindRestoreItemAction): framework.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...), diff --git a/pkg/plugin/clientmgmt/process/client_builder_test.go b/pkg/plugin/clientmgmt/process/client_builder_test.go index 1b9c77145..2a3f6df61 100644 --- a/pkg/plugin/clientmgmt/process/client_builder_test.go +++ b/pkg/plugin/clientmgmt/process/client_builder_test.go @@ -27,6 +27,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/features" "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/test" ) @@ -60,13 +61,13 @@ func TestClientConfig(t *testing.T) { HandshakeConfig: framework.Handshake(), AllowedProtocols: []hcplugin.Protocol{hcplugin.ProtocolGRPC}, Plugins: map[string]hcplugin.Plugin{ - string(framework.PluginKindBackupItemAction): framework.NewBackupItemActionPlugin(framework.ClientLogger(logger)), - string(framework.PluginKindVolumeSnapshotter): framework.NewVolumeSnapshotterPlugin(framework.ClientLogger(logger)), - string(framework.PluginKindObjectStore): framework.NewObjectStorePlugin(framework.ClientLogger(logger)), - string(framework.PluginKindPluginLister): &framework.PluginListerPlugin{}, - string(framework.PluginKindRestoreItemAction): framework.NewRestoreItemActionPlugin(framework.ClientLogger(logger)), - string(framework.PluginKindDeleteItemAction): framework.NewDeleteItemActionPlugin(framework.ClientLogger(logger)), - string(framework.PluginKindItemSnapshotter): framework.NewItemSnapshotterPlugin(framework.ClientLogger(logger)), + string(common.PluginKindBackupItemAction): framework.NewBackupItemActionPlugin(common.ClientLogger(logger)), + string(common.PluginKindVolumeSnapshotter): framework.NewVolumeSnapshotterPlugin(common.ClientLogger(logger)), + string(common.PluginKindObjectStore): framework.NewObjectStorePlugin(common.ClientLogger(logger)), + string(common.PluginKindPluginLister): &framework.PluginListerPlugin{}, + string(common.PluginKindRestoreItemAction): framework.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...), diff --git a/pkg/plugin/clientmgmt/process/process.go b/pkg/plugin/clientmgmt/process/process.go index 66033768d..b6be27687 100644 --- a/pkg/plugin/clientmgmt/process/process.go +++ b/pkg/plugin/clientmgmt/process/process.go @@ -23,7 +23,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" ) type ProcessFactory interface { @@ -132,7 +132,7 @@ func (r *process) dispense(key KindAndName) (interface{}, error) { } // Currently all plugins except for PluginLister dispense clientDispenser instances. - if clientDispenser, ok := dispensed.(framework.ClientDispenser); ok { + if clientDispenser, ok := dispensed.(common.ClientDispenser); ok { if key.Name == "" { return nil, errors.Errorf("%s plugin requested but name is missing", key.Kind.String()) } diff --git a/pkg/plugin/clientmgmt/process/process_test.go b/pkg/plugin/clientmgmt/process/process_test.go index a44254dbd..ce7c7c07b 100644 --- a/pkg/plugin/clientmgmt/process/process_test.go +++ b/pkg/plugin/clientmgmt/process/process_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/require" "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" ) type mockClientProtocol struct { @@ -96,7 +97,7 @@ func TestDispense(t *testing.T) { key := KindAndName{} if tc.clientDispenser { - key.Kind = framework.PluginKindObjectStore + key.Kind = common.PluginKindObjectStore protocolClient.On("Dispense", key.Kind.String()).Return(clientDispenser, tc.dispenseError) if !tc.missingKeyName { @@ -105,7 +106,7 @@ func TestDispense(t *testing.T) { clientDispenser.On("ClientFor", key.Name).Return(client) } } else { - key.Kind = framework.PluginKindPluginLister + key.Kind = common.PluginKindPluginLister client = &framework.PluginListerGRPCClient{} protocolClient.On("Dispense", key.Kind.String()).Return(client, tc.dispenseError) } diff --git a/pkg/plugin/clientmgmt/process/registry.go b/pkg/plugin/clientmgmt/process/registry.go index 2e51ea2a2..11a6bf43e 100644 --- a/pkg/plugin/clientmgmt/process/registry.go +++ b/pkg/plugin/clientmgmt/process/registry.go @@ -25,6 +25,7 @@ import ( "github.com/sirupsen/logrus" "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/util/filesystem" ) @@ -33,14 +34,14 @@ type Registry interface { // DiscoverPlugins discovers all available plugins. DiscoverPlugins() error // List returns all PluginIdentifiers for kind. - List(kind framework.PluginKind) []framework.PluginIdentifier + List(kind common.PluginKind) []framework.PluginIdentifier // Get returns the PluginIdentifier for kind and name. - Get(kind framework.PluginKind, name string) (framework.PluginIdentifier, error) + Get(kind common.PluginKind, name string) (framework.PluginIdentifier, error) } // KindAndName is a convenience struct that combines a PluginKind and a name. type KindAndName struct { - Kind framework.PluginKind + Kind common.PluginKind Name string } @@ -54,7 +55,7 @@ type registry struct { processFactory ProcessFactory fs filesystem.Interface pluginsByID map[KindAndName]framework.PluginIdentifier - pluginsByKind map[framework.PluginKind][]framework.PluginIdentifier + pluginsByKind map[common.PluginKind][]framework.PluginIdentifier } // NewRegistry returns a new registry. @@ -67,7 +68,7 @@ func NewRegistry(dir string, logger logrus.FieldLogger, logLevel logrus.Level) R processFactory: newProcessFactory(), fs: filesystem.NewFileSystem(), pluginsByID: make(map[KindAndName]framework.PluginIdentifier), - pluginsByKind: make(map[framework.PluginKind][]framework.PluginIdentifier), + pluginsByKind: make(map[common.PluginKind][]framework.PluginIdentifier), } } @@ -110,13 +111,13 @@ func (r *registry) discoverPlugins(commands []string) error { // List returns info about all plugin binaries that implement the given // PluginKind. -func (r *registry) List(kind framework.PluginKind) []framework.PluginIdentifier { +func (r *registry) List(kind common.PluginKind) []framework.PluginIdentifier { return r.pluginsByKind[kind] } // Get returns info about a plugin with the given name and kind, or an // error if one cannot be found. -func (r *registry) Get(kind framework.PluginKind, name string) (framework.PluginIdentifier, error) { +func (r *registry) Get(kind common.PluginKind, name string) (framework.PluginIdentifier, error) { p, found := r.pluginsByID[KindAndName{Kind: kind, Name: name}] if !found { return framework.PluginIdentifier{}, newPluginNotFoundError(kind, name) @@ -182,7 +183,7 @@ func (r *registry) listPlugins(command string) ([]framework.PluginIdentifier, er } defer process.kill() - plugin, err := process.dispense(KindAndName{Kind: framework.PluginKindPluginLister}) + plugin, err := process.dispense(KindAndName{Kind: common.PluginKindPluginLister}) if err != nil { return nil, err } @@ -203,24 +204,33 @@ func (r *registry) register(id framework.PluginIdentifier) error { } // no need to pass list of existing plugins since the check if this exists was done above - if err := framework.ValidatePluginName(id.Name, nil); err != nil { + if err := common.ValidatePluginName(id.Name, nil); err != nil { return errors.Errorf("invalid plugin name %q: %s", id.Name, err) } r.pluginsByID[key] = id r.pluginsByKind[id.Kind] = append(r.pluginsByKind[id.Kind], id) + // if id.Kind is adaptable to newer plugin versions, list it under the other versions as well + // If BackupItemAction is adaptable to BackupItemActionV2, then it would be listed under both + // kinds + if kinds, ok := common.PluginKindsAdaptableTo[id.Kind]; ok { + for _, kind := range kinds { + r.pluginsByKind[kind] = append(r.pluginsByKind[kind], id) + } + } + return nil } // pluginNotFoundError indicates a plugin could not be located for kind and name. type PluginNotFoundError struct { - kind framework.PluginKind + kind common.PluginKind name string } // newPluginNotFoundError returns a new pluginNotFoundError for kind and name. -func newPluginNotFoundError(kind framework.PluginKind, name string) *PluginNotFoundError { +func newPluginNotFoundError(kind common.PluginKind, name string) *PluginNotFoundError { return &PluginNotFoundError{ kind: kind, name: name, diff --git a/pkg/plugin/clientmgmt/restartable_delegate_test.go b/pkg/plugin/clientmgmt/restartable_delegate_test.go index c71d3e276..a69f2e05d 100644 --- a/pkg/plugin/clientmgmt/restartable_delegate_test.go +++ b/pkg/plugin/clientmgmt/restartable_delegate_test.go @@ -25,7 +25,7 @@ import ( "github.com/stretchr/testify/require" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" ) type restartableDelegateTest struct { @@ -43,7 +43,7 @@ type mockable interface { func runRestartableDelegateTests( t *testing.T, - kind framework.PluginKind, + kind common.PluginKind, newRestartable func(key process.KindAndName, p process.RestartableProcess) interface{}, newMock func() mockable, tests ...restartableDelegateTest, diff --git a/pkg/plugin/clientmgmt/restartable_delete_item_action.go b/pkg/plugin/clientmgmt/restartable_delete_item_action.go index 977203aae..ead2b9b09 100644 --- a/pkg/plugin/clientmgmt/restartable_delete_item_action.go +++ b/pkg/plugin/clientmgmt/restartable_delete_item_action.go @@ -20,7 +20,7 @@ import ( "github.com/pkg/errors" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -37,7 +37,7 @@ type restartableDeleteItemAction struct { // NewRestartableDeleteItemAction returns a new restartableDeleteItemAction. func NewRestartableDeleteItemAction(name string, sharedPluginProcess process.RestartableProcess) *restartableDeleteItemAction { r := &restartableDeleteItemAction{ - key: process.KindAndName{Kind: framework.PluginKindDeleteItemAction, Name: name}, + key: process.KindAndName{Kind: common.PluginKindDeleteItemAction, Name: name}, sharedPluginProcess: sharedPluginProcess, } return r diff --git a/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go b/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go index 65fb9646c..bd5d734a4 100644 --- a/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go +++ b/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go @@ -26,7 +26,7 @@ import ( api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks" ) @@ -60,7 +60,7 @@ func TestRestartableGetDeleteItemAction(t *testing.T) { defer p.AssertExpectations(t) name := "pod" - key := process.KindAndName{Kind: framework.PluginKindDeleteItemAction, Name: name} + key := process.KindAndName{Kind: common.PluginKindDeleteItemAction, Name: name} p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) r := NewRestartableDeleteItemAction(name, p) @@ -92,7 +92,7 @@ func TestRestartableDeleteItemActionGetDelegate(t *testing.T) { // Currently broken since this mocks out the restore item action interface p.On("ResetIfNeeded").Return(nil) expected := new(mocks.DeleteItemAction) - key := process.KindAndName{Kind: framework.PluginKindDeleteItemAction, Name: name} + key := process.KindAndName{Kind: common.PluginKindDeleteItemAction, Name: name} p.On("GetByKindAndName", key).Return(expected, nil) a, err = r.getDelegate() @@ -116,7 +116,7 @@ func TestRestartableDeleteItemActionDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, - framework.PluginKindDeleteItemAction, + common.PluginKindDeleteItemAction, func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableDeleteItemAction{ key: key, diff --git a/pkg/plugin/clientmgmt/restartable_item_snapshotter.go b/pkg/plugin/clientmgmt/restartable_item_snapshotter.go index d2743789a..204d6ca22 100644 --- a/pkg/plugin/clientmgmt/restartable_item_snapshotter.go +++ b/pkg/plugin/clientmgmt/restartable_item_snapshotter.go @@ -22,7 +22,7 @@ import ( "github.com/pkg/errors" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "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" ) @@ -35,7 +35,7 @@ type restartableItemSnapshotter struct { // NewRestartableItemSnapshotter returns a new restartableItemSnapshotter. func NewRestartableItemSnapshotter(name string, sharedPluginProcess process.RestartableProcess) *restartableItemSnapshotter { r := &restartableItemSnapshotter{ - key: process.KindAndName{Kind: framework.PluginKindItemSnapshotter, Name: name}, + key: process.KindAndName{Kind: common.PluginKindItemSnapshotter, Name: name}, sharedPluginProcess: sharedPluginProcess, } return r diff --git a/pkg/plugin/clientmgmt/restartable_item_snapshotter_test.go b/pkg/plugin/clientmgmt/restartable_item_snapshotter_test.go index 70d4a934a..5aeca0551 100644 --- a/pkg/plugin/clientmgmt/restartable_item_snapshotter_test.go +++ b/pkg/plugin/clientmgmt/restartable_item_snapshotter_test.go @@ -31,7 +31,7 @@ import ( "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" + "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" ) @@ -65,7 +65,7 @@ func TestRestartableGetItemSnapshotter(t *testing.T) { defer p.AssertExpectations(t) name := "pvc" - key := process.KindAndName{Kind: framework.PluginKindItemSnapshotter, Name: name} + key := process.KindAndName{Kind: common.PluginKindItemSnapshotter, Name: name} p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) r := NewRestartableItemSnapshotter(name, p) @@ -96,7 +96,7 @@ func TestRestartableItemSnapshotterGetDelegate(t *testing.T) { // Happy path p.On("ResetIfNeeded").Return(nil) expected := new(mocks.ItemSnapshotter) - key := process.KindAndName{Kind: framework.PluginKindItemSnapshotter, Name: name} + key := process.KindAndName{Kind: common.PluginKindItemSnapshotter, Name: name} p.On("GetByKindAndName", key).Return(expected, nil) a, err = r.getDelegate() @@ -177,7 +177,7 @@ func TestRestartableItemSnasphotterDelegatedFunctions(t *testing.T) { } runRestartableDelegateTests( t, - framework.PluginKindItemSnapshotter, + common.PluginKindItemSnapshotter, func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableItemSnapshotter{ key: key, diff --git a/pkg/plugin/clientmgmt/restartable_object_store.go b/pkg/plugin/clientmgmt/restartable_object_store.go index 5be111340..a3552bd0a 100644 --- a/pkg/plugin/clientmgmt/restartable_object_store.go +++ b/pkg/plugin/clientmgmt/restartable_object_store.go @@ -23,7 +23,7 @@ import ( "github.com/pkg/errors" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -41,7 +41,7 @@ type restartableObjectStore struct { // NewRestartableObjectStore returns a new restartableObjectStore. func NewRestartableObjectStore(name string, sharedPluginProcess process.RestartableProcess) *restartableObjectStore { - key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} + key := process.KindAndName{Kind: common.PluginKindObjectStore, Name: name} r := &restartableObjectStore{ key: key, sharedPluginProcess: sharedPluginProcess, diff --git a/pkg/plugin/clientmgmt/restartable_object_store_test.go b/pkg/plugin/clientmgmt/restartable_object_store_test.go index b4e94fccc..47699c50b 100644 --- a/pkg/plugin/clientmgmt/restartable_object_store_test.go +++ b/pkg/plugin/clientmgmt/restartable_object_store_test.go @@ -27,7 +27,7 @@ import ( "github.com/stretchr/testify/require" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" providermocks "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks" ) @@ -61,7 +61,7 @@ func TestRestartableGetObjectStore(t *testing.T) { defer p.AssertExpectations(t) name := "aws" - key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} + key := process.KindAndName{Kind: common.PluginKindObjectStore, Name: name} p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) r := &restartableObjectStore{ @@ -86,7 +86,7 @@ func TestRestartableObjectStoreReinitialize(t *testing.T) { defer p.AssertExpectations(t) name := "aws" - key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} + key := process.KindAndName{Kind: common.PluginKindObjectStore, Name: name} r := &restartableObjectStore{ key: key, sharedPluginProcess: p, @@ -119,7 +119,7 @@ func TestRestartableObjectStoreGetDelegate(t *testing.T) { // Reset error p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "aws" - key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} + key := process.KindAndName{Kind: common.PluginKindObjectStore, Name: name} r := &restartableObjectStore{ key: key, sharedPluginProcess: p, @@ -147,7 +147,7 @@ func TestRestartableObjectStoreInit(t *testing.T) { // getObjectStore error name := "aws" - key := process.KindAndName{Kind: framework.PluginKindObjectStore, Name: name} + key := process.KindAndName{Kind: common.PluginKindObjectStore, Name: name} r := &restartableObjectStore{ key: key, sharedPluginProcess: p, @@ -187,7 +187,7 @@ func TestRestartableObjectStoreInit(t *testing.T) { func TestRestartableObjectStoreDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, - framework.PluginKindObjectStore, + common.PluginKindObjectStore, func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableObjectStore{ key: key, diff --git a/pkg/plugin/clientmgmt/restartable_restore_item_action.go b/pkg/plugin/clientmgmt/restartable_restore_item_action.go index c4e6911b4..fdd266d0b 100644 --- a/pkg/plugin/clientmgmt/restartable_restore_item_action.go +++ b/pkg/plugin/clientmgmt/restartable_restore_item_action.go @@ -20,7 +20,7 @@ import ( "github.com/pkg/errors" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -37,7 +37,7 @@ type restartableRestoreItemAction struct { // NewRestartableRestoreItemAction returns a new RestartableRestoreItemAction. func NewRestartableRestoreItemAction(name string, sharedPluginProcess process.RestartableProcess) *restartableRestoreItemAction { r := &restartableRestoreItemAction{ - key: process.KindAndName{Kind: framework.PluginKindRestoreItemAction, Name: name}, + key: process.KindAndName{Kind: common.PluginKindRestoreItemAction, Name: name}, sharedPluginProcess: sharedPluginProcess, } return r diff --git a/pkg/plugin/clientmgmt/restartable_restore_item_action_test.go b/pkg/plugin/clientmgmt/restartable_restore_item_action_test.go index 3d4fd52e9..b91d08bfa 100644 --- a/pkg/plugin/clientmgmt/restartable_restore_item_action_test.go +++ b/pkg/plugin/clientmgmt/restartable_restore_item_action_test.go @@ -26,7 +26,7 @@ import ( v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" "github.com/vmware-tanzu/velero/pkg/restore/mocks" ) @@ -60,7 +60,7 @@ func TestRestartableGetRestoreItemAction(t *testing.T) { defer p.AssertExpectations(t) name := "pod" - key := process.KindAndName{Kind: framework.PluginKindRestoreItemAction, Name: name} + key := process.KindAndName{Kind: common.PluginKindRestoreItemAction, Name: name} p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) r := NewRestartableRestoreItemAction(name, p) @@ -91,7 +91,7 @@ func TestRestartableRestoreItemActionGetDelegate(t *testing.T) { // Happy path p.On("ResetIfNeeded").Return(nil) expected := new(mocks.ItemAction) - key := process.KindAndName{Kind: framework.PluginKindRestoreItemAction, Name: name} + key := process.KindAndName{Kind: common.PluginKindRestoreItemAction, Name: name} p.On("GetByKindAndName", key).Return(expected, nil) a, err = r.getDelegate() @@ -122,7 +122,7 @@ func TestRestartableRestoreItemActionDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, - framework.PluginKindRestoreItemAction, + common.PluginKindRestoreItemAction, func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableRestoreItemAction{ key: key, diff --git a/pkg/plugin/clientmgmt/restartable_volume_snapshotter.go b/pkg/plugin/clientmgmt/restartable_volume_snapshotter.go index f8a1a66b0..1252306ea 100644 --- a/pkg/plugin/clientmgmt/restartable_volume_snapshotter.go +++ b/pkg/plugin/clientmgmt/restartable_volume_snapshotter.go @@ -21,7 +21,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -35,9 +35,9 @@ type restartableVolumeSnapshotter struct { config map[string]string } -// NewRestartableVolumeSnapshotter returns a new RestartableVolumeSnapshotter. +// NewRestartableVolumeSnapshotter returns a new restartableVolumeSnapshotter. func NewRestartableVolumeSnapshotter(name string, sharedPluginProcess process.RestartableProcess) *restartableVolumeSnapshotter { - key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} + key := process.KindAndName{Kind: common.PluginKindVolumeSnapshotter, Name: name} r := &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: sharedPluginProcess, diff --git a/pkg/plugin/clientmgmt/restartable_volume_snapshotter_test.go b/pkg/plugin/clientmgmt/restartable_volume_snapshotter_test.go index 8d198ec96..4f8c06f8c 100644 --- a/pkg/plugin/clientmgmt/restartable_volume_snapshotter_test.go +++ b/pkg/plugin/clientmgmt/restartable_volume_snapshotter_test.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" providermocks "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks" ) @@ -60,7 +60,7 @@ func TestRestartableGetVolumeSnapshotter(t *testing.T) { defer p.AssertExpectations(t) name := "aws" - key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} + key := process.KindAndName{Kind: common.PluginKindVolumeSnapshotter, Name: name} p.On("GetByKindAndName", key).Return(tc.plugin, tc.getError) r := &restartableVolumeSnapshotter{ @@ -85,7 +85,7 @@ func TestRestartableVolumeSnapshotterReinitialize(t *testing.T) { defer p.AssertExpectations(t) name := "aws" - key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} + key := process.KindAndName{Kind: common.PluginKindVolumeSnapshotter, Name: name} r := &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: p, @@ -118,7 +118,7 @@ func TestRestartableVolumeSnapshotterGetDelegate(t *testing.T) { // Reset error p.On("ResetIfNeeded").Return(errors.Errorf("reset error")).Once() name := "aws" - key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} + key := process.KindAndName{Kind: common.PluginKindVolumeSnapshotter, Name: name} r := &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: p, @@ -146,7 +146,7 @@ func TestRestartableVolumeSnapshotterInit(t *testing.T) { // getVolumeSnapshottererror name := "aws" - key := process.KindAndName{Kind: framework.PluginKindVolumeSnapshotter, Name: name} + key := process.KindAndName{Kind: common.PluginKindVolumeSnapshotter, Name: name} r := &restartableVolumeSnapshotter{ key: key, sharedPluginProcess: p, @@ -198,7 +198,7 @@ func TestRestartableVolumeSnapshotterDelegatedFunctions(t *testing.T) { runRestartableDelegateTests( t, - framework.PluginKindVolumeSnapshotter, + common.PluginKindVolumeSnapshotter, func(key process.KindAndName, p process.RestartableProcess) interface{} { return &restartableVolumeSnapshotter{ key: key, diff --git a/pkg/plugin/framework/action_resolver.go b/pkg/plugin/framework/action_resolver.go index 345061aac..b1d692fd3 100644 --- a/pkg/plugin/framework/action_resolver.go +++ b/pkg/plugin/framework/action_resolver.go @@ -127,14 +127,14 @@ func NewItemSnapshotterResolver(actions []isv1.ItemSnapshotter) ItemSnapshotterR } type ActionResolver interface { - ResolveAction(helper discovery.Helper, action velero.Applicable) (ResolvedAction, error) + ResolveAction(helper discovery.Helper, action velero.Applicable, log logrus.FieldLogger) (ResolvedAction, error) } type BackupItemActionResolver struct { actions []biav1.BackupItemAction } -func (recv BackupItemActionResolver) ResolveActions(helper discovery.Helper) ([]BackupItemResolvedAction, error) { +func (recv BackupItemActionResolver) ResolveActions(helper discovery.Helper, log logrus.FieldLogger) ([]BackupItemResolvedAction, error) { var resolved []BackupItemResolvedAction for _, action := range recv.actions { resources, namespaces, selector, err := resolveAction(helper, action) @@ -163,7 +163,7 @@ type RestoreItemActionResolver struct { actions []velero.RestoreItemAction } -func (recv RestoreItemActionResolver) ResolveActions(helper discovery.Helper) ([]RestoreItemResolvedAction, error) { +func (recv RestoreItemActionResolver) ResolveActions(helper discovery.Helper, log logrus.FieldLogger) ([]RestoreItemResolvedAction, error) { var resolved []RestoreItemResolvedAction for _, action := range recv.actions { resources, namespaces, selector, err := resolveAction(helper, action) @@ -192,7 +192,7 @@ type DeleteItemActionResolver struct { actions []velero.DeleteItemAction } -func (recv DeleteItemActionResolver) ResolveActions(helper discovery.Helper) ([]DeleteItemResolvedAction, error) { +func (recv DeleteItemActionResolver) ResolveActions(helper discovery.Helper, log logrus.FieldLogger) ([]DeleteItemResolvedAction, error) { var resolved []DeleteItemResolvedAction for _, action := range recv.actions { resources, namespaces, selector, err := resolveAction(helper, action) @@ -221,7 +221,7 @@ type ItemSnapshotterResolver struct { actions []isv1.ItemSnapshotter } -func (recv ItemSnapshotterResolver) ResolveActions(helper discovery.Helper) ([]ItemSnapshotterResolvedAction, error) { +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) diff --git a/pkg/plugin/framework/backup_item_action.go b/pkg/plugin/framework/backup_item_action.go index 8780c7826..8f6bc7554 100644 --- a/pkg/plugin/framework/backup_item_action.go +++ b/pkg/plugin/framework/backup_item_action.go @@ -21,6 +21,7 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" protobiav1 "github.com/vmware-tanzu/velero/pkg/plugin/generated" ) @@ -29,16 +30,16 @@ import ( // interface. type BackupItemActionPlugin struct { plugin.NetRPCUnsupportedPlugin - *pluginBase + *common.PluginBase } // GRPCClient returns a clientDispenser for BackupItemAction gRPC clients. func (p *BackupItemActionPlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, clientConn *grpc.ClientConn) (interface{}, error) { - return newClientDispenser(p.clientLogger, clientConn, newBackupItemActionGRPCClient), nil + return common.NewClientDispenser(p.ClientLogger, clientConn, newBackupItemActionGRPCClient), nil } // GRPCServer registers a BackupItemAction gRPC server. func (p *BackupItemActionPlugin) GRPCServer(_ *plugin.GRPCBroker, server *grpc.Server) error { - protobiav1.RegisterBackupItemActionServer(server, &BackupItemActionGRPCServer{mux: p.serverMux}) + protobiav1.RegisterBackupItemActionServer(server, &BackupItemActionGRPCServer{mux: p.ServerMux}) return nil } diff --git a/pkg/plugin/framework/backup_item_action_client.go b/pkg/plugin/framework/backup_item_action_client.go index 4756ab392..50101975f 100644 --- a/pkg/plugin/framework/backup_item_action_client.go +++ b/pkg/plugin/framework/backup_item_action_client.go @@ -27,39 +27,40 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" protobiav1 "github.com/vmware-tanzu/velero/pkg/plugin/generated" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) // NewBackupItemActionPlugin constructs a BackupItemActionPlugin. -func NewBackupItemActionPlugin(options ...PluginOption) *BackupItemActionPlugin { +func NewBackupItemActionPlugin(options ...common.PluginOption) *BackupItemActionPlugin { return &BackupItemActionPlugin{ - pluginBase: newPluginBase(options...), + PluginBase: common.NewPluginBase(options...), } } // BackupItemActionGRPCClient implements the backup/ItemAction interface and uses a // gRPC client to make calls to the plugin server. type BackupItemActionGRPCClient struct { - *clientBase + *common.ClientBase grpcClient protobiav1.BackupItemActionClient } -func newBackupItemActionGRPCClient(base *clientBase, clientConn *grpc.ClientConn) interface{} { +func newBackupItemActionGRPCClient(base *common.ClientBase, clientConn *grpc.ClientConn) interface{} { return &BackupItemActionGRPCClient{ - clientBase: base, + ClientBase: base, grpcClient: protobiav1.NewBackupItemActionClient(clientConn), } } func (c *BackupItemActionGRPCClient) AppliesTo() (velero.ResourceSelector, error) { req := &protobiav1.BackupItemActionAppliesToRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, } res, err := c.grpcClient.AppliesTo(context.Background(), req) if err != nil { - return velero.ResourceSelector{}, fromGRPCError(err) + return velero.ResourceSelector{}, common.FromGRPCError(err) } if res.ResourceSelector == nil { @@ -87,14 +88,14 @@ func (c *BackupItemActionGRPCClient) Execute(item runtime.Unstructured, backup * } req := &protobiav1.ExecuteRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Item: itemJSON, Backup: backupJSON, } res, err := c.grpcClient.Execute(context.Background(), req) if err != nil { - return nil, nil, fromGRPCError(err) + return nil, nil, common.FromGRPCError(err) } var updatedItem unstructured.Unstructured diff --git a/pkg/plugin/framework/backup_item_action_server.go b/pkg/plugin/framework/backup_item_action_server.go index fec8f0700..bde6c2148 100644 --- a/pkg/plugin/framework/backup_item_action_server.go +++ b/pkg/plugin/framework/backup_item_action_server.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" proto "github.com/vmware-tanzu/velero/pkg/plugin/generated" protobiav1 "github.com/vmware-tanzu/velero/pkg/plugin/generated" "github.com/vmware-tanzu/velero/pkg/plugin/velero" @@ -33,11 +34,11 @@ import ( // BackupItemActionGRPCServer implements the proto-generated BackupItemAction interface, and accepts // gRPC calls and forwards them to an implementation of the pluggable interface. type BackupItemActionGRPCServer struct { - mux *serverMux + mux *common.ServerMux } func (s *BackupItemActionGRPCServer) getImpl(name string) (biav1.BackupItemAction, error) { - impl, err := s.mux.getHandler(name) + impl, err := s.mux.GetHandler(name) if err != nil { return nil, err } @@ -54,19 +55,19 @@ func (s *BackupItemActionGRPCServer) AppliesTo( ctx context.Context, req *protobiav1.BackupItemActionAppliesToRequest) ( response *protobiav1.BackupItemActionAppliesToResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } resourceSelector, err := impl.AppliesTo() if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &protobiav1.BackupItemActionAppliesToResponse{ @@ -83,29 +84,29 @@ func (s *BackupItemActionGRPCServer) AppliesTo( func (s *BackupItemActionGRPCServer) Execute( ctx context.Context, req *protobiav1.ExecuteRequest) (response *protobiav1.ExecuteResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var item unstructured.Unstructured var backup api.Backup if err := json.Unmarshal(req.Item, &item); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } if err := json.Unmarshal(req.Backup, &backup); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } updatedItem, additionalItems, err := impl.Execute(&item, &backup) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } // If the plugin implementation returned a nil updatedItem (meaning no modifications), reset updatedItem to the @@ -116,7 +117,7 @@ func (s *BackupItemActionGRPCServer) Execute( } else { updatedItemJSON, err = json.Marshal(updatedItem.UnstructuredContent()) if err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } } diff --git a/pkg/plugin/framework/backup_item_action_test.go b/pkg/plugin/framework/backup_item_action_test.go index 32d7ea551..a88aaf853 100644 --- a/pkg/plugin/framework/backup_item_action_test.go +++ b/pkg/plugin/framework/backup_item_action_test.go @@ -29,10 +29,11 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - "github.com/vmware-tanzu/velero/pkg/backup/mocks" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" proto "github.com/vmware-tanzu/velero/pkg/plugin/generated" protobiav1 "github.com/vmware-tanzu/velero/pkg/plugin/generated" "github.com/vmware-tanzu/velero/pkg/plugin/velero" + mocks "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks/backupitemaction/v1" velerotest "github.com/vmware-tanzu/velero/pkg/test" ) @@ -147,16 +148,16 @@ func TestBackupItemActionGRPCServerExecute(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - itemAction := &mocks.ItemAction{} + itemAction := &mocks.BackupItemAction{} defer itemAction.AssertExpectations(t) if !test.skipMock { itemAction.On("Execute", &validItemObject, &validBackupObject).Return(test.implUpdatedItem, test.implAdditionalItems, test.implError) } - s := &BackupItemActionGRPCServer{mux: &serverMux{ - serverLog: velerotest.NewLogger(), - handlers: map[string]interface{}{ + s := &BackupItemActionGRPCServer{mux: &common.ServerMux{ + ServerLog: velerotest.NewLogger(), + Handlers: map[string]interface{}{ "xyz": itemAction, }, }} diff --git a/pkg/plugin/framework/client_dispenser.go b/pkg/plugin/framework/common/client_dispenser.go similarity index 86% rename from pkg/plugin/framework/client_dispenser.go rename to pkg/plugin/framework/common/client_dispenser.go index 83e934d72..1abb11c2d 100644 --- a/pkg/plugin/framework/client_dispenser.go +++ b/pkg/plugin/framework/common/client_dispenser.go @@ -14,17 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ -package framework +package common import ( "github.com/sirupsen/logrus" "google.golang.org/grpc" ) -// clientBase implements client and contains shared fields common to all clients. -type clientBase struct { - plugin string - logger logrus.FieldLogger +// ClientBase implements client and contains shared fields common to all clients. +type ClientBase struct { + Plugin string + Logger logrus.FieldLogger } type ClientDispenser interface { @@ -44,10 +44,10 @@ type clientDispenser struct { clients map[string]interface{} } -type clientInitFunc func(base *clientBase, clientConn *grpc.ClientConn) interface{} +type clientInitFunc func(base *ClientBase, clientConn *grpc.ClientConn) interface{} // newClientDispenser creates a new clientDispenser. -func newClientDispenser(logger logrus.FieldLogger, clientConn *grpc.ClientConn, initFunc clientInitFunc) *clientDispenser { +func NewClientDispenser(logger logrus.FieldLogger, clientConn *grpc.ClientConn, initFunc clientInitFunc) *clientDispenser { return &clientDispenser{ clientConn: clientConn, logger: logger, @@ -63,9 +63,9 @@ func (cd *clientDispenser) ClientFor(name string) interface{} { return client } - base := &clientBase{ - plugin: name, - logger: cd.logger, + base := &ClientBase{ + Plugin: name, + Logger: cd.logger, } // Initialize the plugin (e.g. newBackupItemActionGRPCClient()) client := cd.initFunc(base, cd.clientConn) diff --git a/pkg/plugin/framework/client_dispenser_test.go b/pkg/plugin/framework/common/client_dispenser_test.go similarity index 83% rename from pkg/plugin/framework/client_dispenser_test.go rename to pkg/plugin/framework/common/client_dispenser_test.go index 9ec526669..bd1461658 100644 --- a/pkg/plugin/framework/client_dispenser_test.go +++ b/pkg/plugin/framework/common/client_dispenser_test.go @@ -13,7 +13,7 @@ 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 +package common import ( "testing" @@ -26,7 +26,7 @@ import ( ) type fakeClient struct { - base *clientBase + base *ClientBase clientConn *grpc.ClientConn } @@ -36,11 +36,11 @@ func TestNewClientDispenser(t *testing.T) { clientConn := new(grpc.ClientConn) c := 3 - initFunc := func(base *clientBase, clientConn *grpc.ClientConn) interface{} { + initFunc := func(base *ClientBase, clientConn *grpc.ClientConn) interface{} { return c } - cd := newClientDispenser(logger, clientConn, initFunc) + cd := NewClientDispenser(logger, clientConn, initFunc) assert.Equal(t, clientConn, cd.clientConn) assert.NotNil(t, cd.clients) assert.Empty(t, cd.clients) @@ -52,23 +52,23 @@ func TestClientFor(t *testing.T) { c := new(fakeClient) count := 0 - initFunc := func(base *clientBase, clientConn *grpc.ClientConn) interface{} { + initFunc := func(base *ClientBase, clientConn *grpc.ClientConn) interface{} { c.base = base c.clientConn = clientConn count++ return c } - cd := newClientDispenser(logger, clientConn, initFunc) + cd := NewClientDispenser(logger, clientConn, initFunc) actual := cd.ClientFor("pod") require.IsType(t, &fakeClient{}, actual) typed := actual.(*fakeClient) assert.Equal(t, 1, count) assert.Equal(t, &typed, &c) - expectedBase := &clientBase{ - plugin: "pod", - logger: logger, + expectedBase := &ClientBase{ + Plugin: "pod", + Logger: logger, } assert.Equal(t, expectedBase, typed.base) assert.Equal(t, clientConn, typed.clientConn) diff --git a/pkg/plugin/framework/client_errors.go b/pkg/plugin/framework/common/client_errors.go similarity index 84% rename from pkg/plugin/framework/client_errors.go rename to pkg/plugin/framework/common/client_errors.go index adad199db..377851aa8 100644 --- a/pkg/plugin/framework/client_errors.go +++ b/pkg/plugin/framework/common/client_errors.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package framework +package common import ( "google.golang.org/grpc/status" @@ -22,7 +22,7 @@ import ( proto "github.com/vmware-tanzu/velero/pkg/plugin/generated" ) -// fromGRPCError takes a gRPC status error, extracts a stack trace +// FromGRPCError takes a gRPC status error, extracts a stack trace // from the details if it exists, and returns an error that can // provide information about where it was created. // @@ -30,7 +30,7 @@ import ( // all errors returned from the plugin server before they're passed back to // the rest of the Velero codebase. This will enable them to display location // information when they're logged. -func fromGRPCError(err error) error { +func FromGRPCError(err error) error { statusErr, ok := status.FromError(err) if !ok { return statusErr.Err() @@ -39,7 +39,7 @@ func fromGRPCError(err error) error { for _, detail := range statusErr.Details() { switch t := detail.(type) { case *proto.Stack: - return &protoStackError{ + return &ProtoStackError{ error: err, stack: t, } @@ -49,12 +49,12 @@ func fromGRPCError(err error) error { return err } -type protoStackError struct { +type ProtoStackError struct { error stack *proto.Stack } -func (e *protoStackError) File() string { +func (e *ProtoStackError) File() string { if e.stack == nil || len(e.stack.Frames) < 1 { return "" } @@ -62,7 +62,7 @@ func (e *protoStackError) File() string { return e.stack.Frames[0].File } -func (e *protoStackError) Line() int32 { +func (e *ProtoStackError) Line() int32 { if e.stack == nil || len(e.stack.Frames) < 1 { return 0 } @@ -70,7 +70,7 @@ func (e *protoStackError) Line() int32 { return e.stack.Frames[0].Line } -func (e *protoStackError) Function() string { +func (e *ProtoStackError) Function() string { if e.stack == nil || len(e.stack.Frames) < 1 { return "" } diff --git a/pkg/plugin/framework/handle_panic.go b/pkg/plugin/framework/common/handle_panic.go similarity index 84% rename from pkg/plugin/framework/handle_panic.go rename to pkg/plugin/framework/common/handle_panic.go index 4ea0ec2b5..e4324898d 100644 --- a/pkg/plugin/framework/handle_panic.go +++ b/pkg/plugin/framework/common/handle_panic.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package framework +package common import ( "runtime/debug" @@ -23,8 +23,8 @@ import ( "google.golang.org/grpc/codes" ) -// handlePanic is a panic handler for the server half of velero plugins. -func handlePanic(p interface{}) error { +// HandlePanic is a panic handler for the server half of velero plugins. +func HandlePanic(p interface{}) error { if p == nil { return nil } @@ -37,7 +37,7 @@ func handlePanic(p interface{}) error { if panicErr, ok := p.(error); !ok { err = errors.Errorf("plugin panicked: %v", p) } else { - if _, ok := panicErr.(stackTracer); ok { + if _, ok := panicErr.(StackTracer); ok { err = panicErr } else { errWithStacktrace := errors.Errorf("%v, stack trace: %s", panicErr, debug.Stack()) @@ -45,5 +45,5 @@ func handlePanic(p interface{}) error { } } - return newGRPCErrorWithCode(err, codes.Aborted) + return NewGRPCErrorWithCode(err, codes.Aborted) } diff --git a/pkg/plugin/framework/plugin_base.go b/pkg/plugin/framework/common/plugin_base.go similarity index 65% rename from pkg/plugin/framework/plugin_base.go rename to pkg/plugin/framework/common/plugin_base.go index 4a97fa47b..12e444b74 100644 --- a/pkg/plugin/framework/plugin_base.go +++ b/pkg/plugin/framework/common/plugin_base.go @@ -14,35 +14,35 @@ See the License for the specific language governing permissions and limitations under the License. */ -package framework +package common import ( "github.com/sirupsen/logrus" ) -type pluginBase struct { - clientLogger logrus.FieldLogger - *serverMux +type PluginBase struct { + ClientLogger logrus.FieldLogger + *ServerMux } -func newPluginBase(options ...PluginOption) *pluginBase { - base := new(pluginBase) +func NewPluginBase(options ...PluginOption) *PluginBase { + base := new(PluginBase) for _, option := range options { option(base) } return base } -type PluginOption func(base *pluginBase) +type PluginOption func(base *PluginBase) func ClientLogger(logger logrus.FieldLogger) PluginOption { - return func(base *pluginBase) { - base.clientLogger = logger + return func(base *PluginBase) { + base.ClientLogger = logger } } -func serverLogger(logger logrus.FieldLogger) PluginOption { - return func(base *pluginBase) { - base.serverMux = newServerMux(logger) +func ServerLogger(logger logrus.FieldLogger) PluginOption { + return func(base *PluginBase) { + base.ServerMux = NewServerMux(logger) } } diff --git a/pkg/plugin/framework/plugin_base_test.go b/pkg/plugin/framework/common/plugin_base_test.go similarity index 84% rename from pkg/plugin/framework/plugin_base_test.go rename to pkg/plugin/framework/common/plugin_base_test.go index 3d2573258..04e066d0c 100644 --- a/pkg/plugin/framework/plugin_base_test.go +++ b/pkg/plugin/framework/common/plugin_base_test.go @@ -13,7 +13,7 @@ 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 +package common import ( "testing" @@ -24,17 +24,17 @@ import ( ) func TestClientLogger(t *testing.T) { - base := &pluginBase{} + base := &PluginBase{} logger := test.NewLogger() f := ClientLogger(logger) f(base) - assert.Equal(t, logger, base.clientLogger) + assert.Equal(t, logger, base.ClientLogger) } func TestServerLogger(t *testing.T) { - base := &pluginBase{} + base := &PluginBase{} logger := test.NewLogger() - f := serverLogger(logger) + f := ServerLogger(logger) f(base) - assert.Equal(t, newServerMux(logger), base.serverMux) + assert.Equal(t, NewServerMux(logger), base.ServerMux) } diff --git a/pkg/plugin/framework/plugin_kinds.go b/pkg/plugin/framework/common/plugin_kinds.go similarity index 89% rename from pkg/plugin/framework/plugin_kinds.go rename to pkg/plugin/framework/common/plugin_kinds.go index f48f7f498..2e0119e2f 100644 --- a/pkg/plugin/framework/plugin_kinds.go +++ b/pkg/plugin/framework/common/plugin_kinds.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package framework +package common // PluginKind is a type alias for a string that describes // the kind of a Velero-supported plugin. @@ -48,6 +48,11 @@ const ( PluginKindPluginLister PluginKind = "PluginLister" ) +// If there are plugin kinds that are adaptable to newer API versions, list them here. +// The older (adaptable) version is the key, and the value is the full list of newer +// plugin kinds that are capable of adapting it. +var PluginKindsAdaptableTo = map[PluginKind][]PluginKind{} + // AllPluginKinds contains all the valid plugin kinds that Velero supports, excluding PluginLister because that is not a // kind that a developer would ever need to implement (it's handled by Velero and the Velero plugin library code). func AllPluginKinds() map[string]PluginKind { diff --git a/pkg/plugin/framework/server_errors.go b/pkg/plugin/framework/common/server_errors.go similarity index 78% rename from pkg/plugin/framework/server_errors.go rename to pkg/plugin/framework/common/server_errors.go index 55f8859fd..7763d4e9e 100644 --- a/pkg/plugin/framework/server_errors.go +++ b/pkg/plugin/framework/common/server_errors.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package framework +package common import ( goproto "github.com/golang/protobuf/proto" @@ -26,13 +26,13 @@ import ( "github.com/vmware-tanzu/velero/pkg/util/logging" ) -// newGRPCErrorWithCode wraps err in a gRPC status error with the error's stack trace +// NewGRPCErrorWithCode wraps err in a gRPC status error with the error's stack trace // included in the details if it exists. This provides an easy way to send // stack traces from plugin servers across the wire to the plugin client. // // This function should be used in the internal plugin server code to wrap // all errors before they're returned. -func newGRPCErrorWithCode(err error, code codes.Code, details ...goproto.Message) error { +func NewGRPCErrorWithCode(err error, code codes.Code, details ...goproto.Message) error { // if it's already a gRPC status error, use it; otherwise, create a new one statusErr, ok := status.FromError(err) if !ok { @@ -40,7 +40,7 @@ func newGRPCErrorWithCode(err error, code codes.Code, details ...goproto.Message } // get a Stack for the error and add it to details - if stack := errorStack(err); stack != nil { + if stack := ErrorStack(err); stack != nil { details = append(details, stack) } @@ -52,16 +52,16 @@ func newGRPCErrorWithCode(err error, code codes.Code, details ...goproto.Message return statusErr.Err() } -// newGRPCError is a convenience function for creating a new gRPC error +// NewGRPCError is a convenience function for creating a new gRPC error // with code = codes.Unknown -func newGRPCError(err error, details ...goproto.Message) error { - return newGRPCErrorWithCode(err, codes.Unknown, details...) +func NewGRPCError(err error, details ...goproto.Message) error { + return NewGRPCErrorWithCode(err, codes.Unknown, details...) } -// errorStack gets a stack trace, if it exists, from the provided error, and +// ErrorStack gets a stack trace, if it exists, from the provided error, and // returns it as a *proto.Stack. -func errorStack(err error) *proto.Stack { - stackTracer, ok := err.(stackTracer) +func ErrorStack(err error) *proto.Stack { + stackTracer, ok := err.(StackTracer) if !ok { return nil } @@ -80,6 +80,6 @@ func errorStack(err error) *proto.Stack { return stackTrace } -type stackTracer interface { +type StackTracer interface { StackTrace() errors.StackTrace } diff --git a/pkg/plugin/framework/server_mux.go b/pkg/plugin/framework/common/server_mux.go similarity index 78% rename from pkg/plugin/framework/server_mux.go rename to pkg/plugin/framework/common/server_mux.go index 4babea384..960975c7e 100644 --- a/pkg/plugin/framework/server_mux.go +++ b/pkg/plugin/framework/common/server_mux.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package framework +package common import ( "strings" @@ -29,42 +29,42 @@ import ( // (ObjectStore, VolumeSnapshotter, BackupItemAction, RestoreItemAction). type HandlerInitializer func(logger logrus.FieldLogger) (interface{}, error) -// serverMux manages multiple implementations of a single plugin kind, such as pod and pvc BackupItemActions. -type serverMux struct { +// ServerMux manages multiple implementations of a single plugin kind, such as pod and pvc BackupItemActions. +type ServerMux struct { kind PluginKind initializers map[string]HandlerInitializer - handlers map[string]interface{} - serverLog logrus.FieldLogger + Handlers map[string]interface{} + ServerLog logrus.FieldLogger } -// newServerMux returns a new serverMux. -func newServerMux(logger logrus.FieldLogger) *serverMux { - return &serverMux{ +// NewServerMux returns a new ServerMux. +func NewServerMux(logger logrus.FieldLogger) *ServerMux { + return &ServerMux{ initializers: make(map[string]HandlerInitializer), - handlers: make(map[string]interface{}), - serverLog: logger, + Handlers: make(map[string]interface{}), + ServerLog: logger, } } // register validates the plugin name and registers the // initializer for the given name. -func (m *serverMux) register(name string, f HandlerInitializer) { - if err := ValidatePluginName(name, m.names()); err != nil { - m.serverLog.Errorf("invalid plugin name %q: %s", name, err) +func (m *ServerMux) Register(name string, f HandlerInitializer) { + if err := ValidatePluginName(name, m.Names()); err != nil { + m.ServerLog.Errorf("invalid plugin name %q: %s", name, err) return } m.initializers[name] = f } // names returns a list of all registered implementations. -func (m *serverMux) names() []string { +func (m *ServerMux) Names() []string { return sets.StringKeySet(m.initializers).List() } -// getHandler returns the instance for a plugin with the given name. If an instance has already been initialized, +// GetHandler returns the instance for a plugin with the given name. If an instance has already been initialized, // that is returned. Otherwise, the instance is initialized by calling its initialization function. -func (m *serverMux) getHandler(name string) (interface{}, error) { - if instance, found := m.handlers[name]; found { +func (m *ServerMux) GetHandler(name string) (interface{}, error) { + if instance, found := m.Handlers[name]; found { return instance, nil } @@ -73,14 +73,14 @@ func (m *serverMux) getHandler(name string) (interface{}, error) { return nil, errors.Errorf("%v plugin: %s was not found or has an invalid name format", m.kind, name) } - instance, err := initializer(m.serverLog) + instance, err := initializer(m.ServerLog) if err != nil { return nil, err } - m.handlers[name] = instance + m.Handlers[name] = instance - return m.handlers[name], nil + return m.Handlers[name], nil } // ValidatePluginName checks if the given name: diff --git a/pkg/plugin/framework/server_mux_test.go b/pkg/plugin/framework/common/server_mux_test.go similarity index 99% rename from pkg/plugin/framework/server_mux_test.go rename to pkg/plugin/framework/common/server_mux_test.go index 1a9be9a68..1e84555f3 100644 --- a/pkg/plugin/framework/server_mux_test.go +++ b/pkg/plugin/framework/common/server_mux_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package framework +package common import ( "strings" diff --git a/pkg/plugin/framework/delete_item_action.go b/pkg/plugin/framework/delete_item_action.go index fc9be502c..7d70938ca 100644 --- a/pkg/plugin/framework/delete_item_action.go +++ b/pkg/plugin/framework/delete_item_action.go @@ -21,6 +21,7 @@ import ( "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" ) @@ -29,16 +30,16 @@ import ( // interface. type DeleteItemActionPlugin struct { plugin.NetRPCUnsupportedPlugin - *pluginBase + *common.PluginBase } // GRPCClient returns a RestoreItemAction gRPC client. func (p *DeleteItemActionPlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, clientConn *grpc.ClientConn) (interface{}, error) { - return newClientDispenser(p.clientLogger, clientConn, newDeleteItemActionGRPCClient), nil + return common.NewClientDispenser(p.ClientLogger, clientConn, newDeleteItemActionGRPCClient), nil } // GRPCServer registers a DeleteItemAction gRPC server. func (p *DeleteItemActionPlugin) GRPCServer(_ *plugin.GRPCBroker, server *grpc.Server) error { - proto.RegisterDeleteItemActionServer(server, &DeleteItemActionGRPCServer{mux: p.serverMux}) + proto.RegisterDeleteItemActionServer(server, &DeleteItemActionGRPCServer{mux: p.ServerMux}) return nil } diff --git a/pkg/plugin/framework/delete_item_action_client.go b/pkg/plugin/framework/delete_item_action_client.go index e9adae6d0..4988d5f08 100644 --- a/pkg/plugin/framework/delete_item_action_client.go +++ b/pkg/plugin/framework/delete_item_action_client.go @@ -23,6 +23,7 @@ import ( "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" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -30,30 +31,30 @@ import ( var _ velero.DeleteItemAction = &DeleteItemActionGRPCClient{} // NewDeleteItemActionPlugin constructs a DeleteItemActionPlugin. -func NewDeleteItemActionPlugin(options ...PluginOption) *DeleteItemActionPlugin { +func NewDeleteItemActionPlugin(options ...common.PluginOption) *DeleteItemActionPlugin { return &DeleteItemActionPlugin{ - pluginBase: newPluginBase(options...), + PluginBase: common.NewPluginBase(options...), } } // DeleteItemActionGRPCClient implements the backup/ItemAction interface and uses a // gRPC client to make calls to the plugin server. type DeleteItemActionGRPCClient struct { - *clientBase + *common.ClientBase grpcClient proto.DeleteItemActionClient } -func newDeleteItemActionGRPCClient(base *clientBase, clientConn *grpc.ClientConn) interface{} { +func newDeleteItemActionGRPCClient(base *common.ClientBase, clientConn *grpc.ClientConn) interface{} { return &DeleteItemActionGRPCClient{ - clientBase: base, + ClientBase: base, grpcClient: proto.NewDeleteItemActionClient(clientConn), } } func (c *DeleteItemActionGRPCClient) AppliesTo() (velero.ResourceSelector, error) { - res, err := c.grpcClient.AppliesTo(context.Background(), &proto.DeleteItemActionAppliesToRequest{Plugin: c.plugin}) + res, err := c.grpcClient.AppliesTo(context.Background(), &proto.DeleteItemActionAppliesToRequest{Plugin: c.Plugin}) if err != nil { - return velero.ResourceSelector{}, fromGRPCError(err) + return velero.ResourceSelector{}, common.FromGRPCError(err) } if res.ResourceSelector == nil { @@ -81,14 +82,14 @@ func (c *DeleteItemActionGRPCClient) Execute(input *velero.DeleteItemActionExecu } req := &proto.DeleteItemActionExecuteRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Item: itemJSON, Backup: backupJSON, } // First return item is just an empty struct no matter what. if _, err = c.grpcClient.Execute(context.Background(), req); err != nil { - return fromGRPCError(err) + return common.FromGRPCError(err) } return nil diff --git a/pkg/plugin/framework/delete_item_action_server.go b/pkg/plugin/framework/delete_item_action_server.go index d9d3a7dc7..e298969d1 100644 --- a/pkg/plugin/framework/delete_item_action_server.go +++ b/pkg/plugin/framework/delete_item_action_server.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "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" ) @@ -31,11 +32,11 @@ import ( // DeleteItemActionGRPCServer implements the proto-generated DeleteItemActionServer interface, and accepts // gRPC calls and forwards them to an implementation of the pluggable interface. type DeleteItemActionGRPCServer struct { - mux *serverMux + mux *common.ServerMux } func (s *DeleteItemActionGRPCServer) getImpl(name string) (velero.DeleteItemAction, error) { - impl, err := s.mux.getHandler(name) + impl, err := s.mux.GetHandler(name) if err != nil { return nil, err } @@ -50,19 +51,19 @@ func (s *DeleteItemActionGRPCServer) getImpl(name string) (velero.DeleteItemActi func (s *DeleteItemActionGRPCServer) AppliesTo(ctx context.Context, req *proto.DeleteItemActionAppliesToRequest) (response *proto.DeleteItemActionAppliesToResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } resourceSelector, err := impl.AppliesTo() if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.DeleteItemActionAppliesToResponse{ @@ -78,14 +79,14 @@ func (s *DeleteItemActionGRPCServer) AppliesTo(ctx context.Context, req *proto.D func (s *DeleteItemActionGRPCServer) Execute(ctx context.Context, req *proto.DeleteItemActionExecuteRequest) (_ *proto.Empty, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var ( @@ -94,18 +95,18 @@ func (s *DeleteItemActionGRPCServer) Execute(ctx context.Context, req *proto.Del ) if err := json.Unmarshal(req.Item, &item); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } if err = json.Unmarshal(req.Backup, &backup); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } if err := impl.Execute(&velero.DeleteItemActionExecuteInput{ Item: &item, Backup: &backup, }); err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.Empty{}, nil diff --git a/pkg/plugin/framework/interface.go b/pkg/plugin/framework/interface.go index 1394e8e82..4eeb3049b 100644 --- a/pkg/plugin/framework/interface.go +++ b/pkg/plugin/framework/interface.go @@ -24,5 +24,5 @@ type Interface interface { // names returns a list of all the registered implementations for this plugin (such as "pod" and "pvc" for // BackupItemAction). - names() []string + Names() []string } diff --git a/pkg/plugin/framework/item_snapshotter.go b/pkg/plugin/framework/item_snapshotter.go index 6e6f91439..f9af50e68 100644 --- a/pkg/plugin/framework/item_snapshotter.go +++ b/pkg/plugin/framework/item_snapshotter.go @@ -21,6 +21,7 @@ import ( "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" ) @@ -29,16 +30,16 @@ import ( // interface. type ItemSnapshotterPlugin struct { plugin.NetRPCUnsupportedPlugin - *pluginBase + *common.PluginBase } // GRPCClient returns a clientDispenser for ItemSnapshotter gRPC clients. func (p *ItemSnapshotterPlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, clientConn *grpc.ClientConn) (interface{}, error) { - return newClientDispenser(p.clientLogger, clientConn, newItemSnapshotterGRPCClient), nil + 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}) + proto.RegisterItemSnapshotterServer(server, &ItemSnapshotterGRPCServer{mux: p.ServerMux}) return nil } diff --git a/pkg/plugin/framework/item_snapshotter_client.go b/pkg/plugin/framework/item_snapshotter_client.go index 23786046a..323c3541b 100644 --- a/pkg/plugin/framework/item_snapshotter_client.go +++ b/pkg/plugin/framework/item_snapshotter_client.go @@ -25,21 +25,22 @@ import ( "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 ...PluginOption) *ItemSnapshotterPlugin { +func NewItemSnapshotterPlugin(options ...common.PluginOption) *ItemSnapshotterPlugin { return &ItemSnapshotterPlugin{ - pluginBase: newPluginBase(options...), + PluginBase: common.NewPluginBase(options...), } } -func newItemSnapshotterGRPCClient(base *clientBase, clientConn *grpc.ClientConn) interface{} { +func newItemSnapshotterGRPCClient(base *common.ClientBase, clientConn *grpc.ClientConn) interface{} { return &ItemSnapshotterGRPCClient{ - clientBase: base, + ClientBase: base, grpcClient: proto.NewItemSnapshotterClient(clientConn), } } @@ -47,13 +48,13 @@ func newItemSnapshotterGRPCClient(base *clientBase, clientConn *grpc.ClientConn) // ItemSnapshotterGRPCClient implements the ItemSnapshotter interface and uses a // gRPC client to make calls to the plugin server. type ItemSnapshotterGRPCClient struct { - *clientBase + *common.ClientBase grpcClient proto.ItemSnapshotterClient } func (recv ItemSnapshotterGRPCClient) Init(config map[string]string) error { req := &proto.ItemSnapshotterInitRequest{ - Plugin: recv.plugin, + Plugin: recv.Plugin, Config: config, } @@ -63,12 +64,12 @@ func (recv ItemSnapshotterGRPCClient) Init(config map[string]string) error { func (recv ItemSnapshotterGRPCClient) AppliesTo() (velero.ResourceSelector, error) { req := &proto.ItemSnapshotterAppliesToRequest{ - Plugin: recv.plugin, + Plugin: recv.Plugin, } res, err := recv.grpcClient.AppliesTo(context.Background(), req) if err != nil { - return velero.ResourceSelector{}, fromGRPCError(err) + return velero.ResourceSelector{}, common.FromGRPCError(err) } if res.ResourceSelector == nil { @@ -95,7 +96,7 @@ func (recv ItemSnapshotterGRPCClient) AlsoHandles(input *isv1.AlsoHandlesInput) return nil, errors.WithStack(err) } req := &proto.AlsoHandlesRequest{ - Plugin: recv.plugin, + Plugin: recv.Plugin, Item: itemJSON, Backup: backupJSON, } @@ -120,7 +121,7 @@ func (recv ItemSnapshotterGRPCClient) SnapshotItem(ctx context.Context, input *i return nil, errors.WithStack(err) } req := &proto.SnapshotItemRequest{ - Plugin: recv.plugin, + Plugin: recv.Plugin, Item: itemJSON, Backup: backupJSON, } @@ -152,7 +153,7 @@ func (recv ItemSnapshotterGRPCClient) Progress(input *isv1.ProgressInput) (*isv1 return nil, errors.WithStack(err) } req := &proto.ProgressRequest{ - Plugin: recv.plugin, + Plugin: recv.Plugin, ItemID: resourceIdentifierToProto(input.ItemID), SnapshotID: input.SnapshotID, Backup: backupJSON, @@ -183,7 +184,7 @@ func (recv ItemSnapshotterGRPCClient) Progress(input *isv1.ProgressInput) (*isv1 func (recv ItemSnapshotterGRPCClient) DeleteSnapshot(ctx context.Context, input *isv1.DeleteSnapshotInput) error { req := &proto.DeleteItemSnapshotRequest{ - Plugin: recv.plugin, + Plugin: recv.Plugin, Params: input.Params, SnapshotID: input.SnapshotID, } @@ -209,7 +210,7 @@ func (recv ItemSnapshotterGRPCClient) CreateItemFromSnapshot(ctx context.Context return nil, errors.WithStack(err) } req := &proto.CreateItemFromSnapshotRequest{ - Plugin: recv.plugin, + Plugin: recv.Plugin, Item: itemJSON, SnapshotID: input.SnapshotID, ItemFromBackup: itemFromBackupJSON, diff --git a/pkg/plugin/framework/item_snapshotter_server.go b/pkg/plugin/framework/item_snapshotter_server.go index d74694757..21ab92110 100644 --- a/pkg/plugin/framework/item_snapshotter_server.go +++ b/pkg/plugin/framework/item_snapshotter_server.go @@ -27,17 +27,18 @@ import ( "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 *serverMux + mux *common.ServerMux } func (recv *ItemSnapshotterGRPCServer) getImpl(name string) (isv1.ItemSnapshotter, error) { - impl, err := recv.mux.getHandler(name) + impl, err := recv.mux.GetHandler(name) if err != nil { return nil, err } @@ -52,19 +53,19 @@ func (recv *ItemSnapshotterGRPCServer) getImpl(name string) (isv1.ItemSnapshotte func (recv *ItemSnapshotterGRPCServer) Init(c context.Context, req *proto.ItemSnapshotterInitRequest) (response *proto.Empty, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := recv.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } err = impl.Init(req.Config) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.Empty{}, nil @@ -72,19 +73,19 @@ func (recv *ItemSnapshotterGRPCServer) Init(c context.Context, req *proto.ItemSn func (recv *ItemSnapshotterGRPCServer) AppliesTo(ctx context.Context, req *proto.ItemSnapshotterAppliesToRequest) (response *proto.ItemSnapshotterAppliesToResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := recv.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } resourceSelector, err := impl.AppliesTo() if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.ItemSnapshotterAppliesToResponse{ @@ -100,23 +101,23 @@ func (recv *ItemSnapshotterGRPCServer) AppliesTo(ctx context.Context, req *proto func (recv *ItemSnapshotterGRPCServer) AlsoHandles(ctx context.Context, req *proto.AlsoHandlesRequest) (res *proto.AlsoHandlesResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := recv.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var item unstructured.Unstructured var backup api.Backup if err := json.Unmarshal(req.Item, &item); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } if err := json.Unmarshal(req.Backup, &backup); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } ahi := isv1.AlsoHandlesInput{ Item: &item, @@ -124,7 +125,7 @@ func (recv *ItemSnapshotterGRPCServer) AlsoHandles(ctx context.Context, req *pro } alsoHandles, err := impl.AlsoHandles(&ahi) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } res = &proto.AlsoHandlesResponse{} @@ -136,23 +137,23 @@ func (recv *ItemSnapshotterGRPCServer) AlsoHandles(ctx context.Context, req *pro func (recv *ItemSnapshotterGRPCServer) SnapshotItem(ctx context.Context, req *proto.SnapshotItemRequest) (res *proto.SnapshotItemResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := recv.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var item unstructured.Unstructured var backup api.Backup if err := json.Unmarshal(req.Item, &item); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } if err := json.Unmarshal(req.Backup, &backup); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } sii := isv1.SnapshotItemInput{ Item: &item, @@ -169,7 +170,7 @@ func (recv *ItemSnapshotterGRPCServer) SnapshotItem(ctx context.Context, req *pr } else { updatedItemJSON, err = json.Marshal(sio.UpdatedItem.UnstructuredContent()) if err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } } res = &proto.SnapshotItemResponse{ @@ -184,18 +185,18 @@ func (recv *ItemSnapshotterGRPCServer) SnapshotItem(ctx context.Context, req *pr func (recv *ItemSnapshotterGRPCServer) Progress(ctx context.Context, req *proto.ProgressRequest) (res *proto.ProgressResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := recv.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var backup api.Backup if err := json.Unmarshal(req.Backup, &backup); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } sipi := &isv1.ProgressInput{ ItemID: protoToResourceIdentifier(req.ItemID), @@ -205,7 +206,7 @@ func (recv *ItemSnapshotterGRPCServer) Progress(ctx context.Context, req *proto. sipo, err := impl.Progress(sipi) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } res = &proto.ProgressResponse{ @@ -223,18 +224,18 @@ func (recv *ItemSnapshotterGRPCServer) Progress(ctx context.Context, req *proto. func (recv *ItemSnapshotterGRPCServer) DeleteSnapshot(ctx context.Context, req *proto.DeleteItemSnapshotRequest) (empty *proto.Empty, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := recv.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var itemFromBackup unstructured.Unstructured if err := json.Unmarshal(req.ItemFromBackup, &itemFromBackup); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } disi := isv1.DeleteSnapshotInput{ @@ -246,36 +247,36 @@ func (recv *ItemSnapshotterGRPCServer) DeleteSnapshot(ctx context.Context, req * err = impl.DeleteSnapshot(ctx, &disi) if err != nil { - return nil, newGRPCError(err) + 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 := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := recv.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var snapshottedItem unstructured.Unstructured if err := json.Unmarshal(req.Item, &snapshottedItem); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } var itemFromBackup unstructured.Unstructured if err := json.Unmarshal(req.Item, &itemFromBackup); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } var restore api.Restore if err := json.Unmarshal(req.Restore, &restore); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } cii := isv1.CreateItemInput{ @@ -289,7 +290,7 @@ func (recv *ItemSnapshotterGRPCServer) CreateItemFromSnapshot(ctx context.Contex cio, err := impl.CreateItemFromSnapshot(ctx, &cii) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var updatedItemJSON []byte @@ -298,7 +299,7 @@ func (recv *ItemSnapshotterGRPCServer) CreateItemFromSnapshot(ctx context.Contex } else { updatedItemJSON, err = json.Marshal(cio.UpdatedItem.UnstructuredContent()) if err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } } res = &proto.CreateItemFromSnapshotResponse{ diff --git a/pkg/plugin/framework/object_store.go b/pkg/plugin/framework/object_store.go index bd7a90cf3..ddf741421 100644 --- a/pkg/plugin/framework/object_store.go +++ b/pkg/plugin/framework/object_store.go @@ -21,6 +21,7 @@ import ( "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" ) @@ -29,17 +30,17 @@ import ( // interface. type ObjectStorePlugin struct { plugin.NetRPCUnsupportedPlugin - *pluginBase + *common.PluginBase } // GRPCClient returns an ObjectStore gRPC client. func (p *ObjectStorePlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, clientConn *grpc.ClientConn) (interface{}, error) { - return newClientDispenser(p.clientLogger, clientConn, newObjectStoreGRPCClient), nil + return common.NewClientDispenser(p.ClientLogger, clientConn, newObjectStoreGRPCClient), nil } // GRPCServer registers an ObjectStore gRPC server. func (p *ObjectStorePlugin) GRPCServer(_ *plugin.GRPCBroker, server *grpc.Server) error { - proto.RegisterObjectStoreServer(server, &ObjectStoreGRPCServer{mux: p.serverMux}) + proto.RegisterObjectStoreServer(server, &ObjectStoreGRPCServer{mux: p.ServerMux}) return nil } diff --git a/pkg/plugin/framework/object_store_client.go b/pkg/plugin/framework/object_store_client.go index 844274907..7f40921c2 100644 --- a/pkg/plugin/framework/object_store_client.go +++ b/pkg/plugin/framework/object_store_client.go @@ -24,28 +24,29 @@ import ( "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" ) const byteChunkSize = 16384 // NewObjectStorePlugin construct an ObjectStorePlugin. -func NewObjectStorePlugin(options ...PluginOption) *ObjectStorePlugin { +func NewObjectStorePlugin(options ...common.PluginOption) *ObjectStorePlugin { return &ObjectStorePlugin{ - pluginBase: newPluginBase(options...), + PluginBase: common.NewPluginBase(options...), } } // ObjectStoreGRPCClient implements the ObjectStore interface and uses a // gRPC client to make calls to the plugin server. type ObjectStoreGRPCClient struct { - *clientBase + *common.ClientBase grpcClient proto.ObjectStoreClient } -func newObjectStoreGRPCClient(base *clientBase, clientConn *grpc.ClientConn) interface{} { +func newObjectStoreGRPCClient(base *common.ClientBase, clientConn *grpc.ClientConn) interface{} { return &ObjectStoreGRPCClient{ - clientBase: base, + ClientBase: base, grpcClient: proto.NewObjectStoreClient(clientConn), } } @@ -55,12 +56,12 @@ func newObjectStoreGRPCClient(base *clientBase, clientConn *grpc.ClientConn) int // cannot be initialized from the provided config. func (c *ObjectStoreGRPCClient) Init(config map[string]string) error { req := &proto.ObjectStoreInitRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Config: config, } if _, err := c.grpcClient.Init(context.Background(), req); err != nil { - return fromGRPCError(err) + return common.FromGRPCError(err) } return nil @@ -71,7 +72,7 @@ func (c *ObjectStoreGRPCClient) Init(config map[string]string) error { func (c *ObjectStoreGRPCClient) PutObject(bucket, key string, body io.Reader) error { stream, err := c.grpcClient.PutObject(context.Background()) if err != nil { - return fromGRPCError(err) + return common.FromGRPCError(err) } // read from the provider io.Reader into chunks, and send each one over @@ -81,7 +82,7 @@ func (c *ObjectStoreGRPCClient) PutObject(bucket, key string, body io.Reader) er n, err := body.Read(chunk) if err == io.EOF { if _, resErr := stream.CloseAndRecv(); resErr != nil { - return fromGRPCError(resErr) + return common.FromGRPCError(resErr) } return nil } @@ -90,8 +91,8 @@ func (c *ObjectStoreGRPCClient) PutObject(bucket, key string, body io.Reader) er return errors.WithStack(err) } - if err := stream.Send(&proto.PutObjectRequest{Plugin: c.plugin, Bucket: bucket, Key: key, Body: chunk[0:n]}); err != nil { - return fromGRPCError(err) + if err := stream.Send(&proto.PutObjectRequest{Plugin: c.Plugin, Bucket: bucket, Key: key, Body: chunk[0:n]}); err != nil { + return common.FromGRPCError(err) } } } @@ -99,7 +100,7 @@ func (c *ObjectStoreGRPCClient) PutObject(bucket, key string, body io.Reader) er // ObjectExists checks if there is an object with the given key in the object storage bucket. func (c *ObjectStoreGRPCClient) ObjectExists(bucket, key string) (bool, error) { req := &proto.ObjectExistsRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Bucket: bucket, Key: key, } @@ -116,14 +117,14 @@ func (c *ObjectStoreGRPCClient) ObjectExists(bucket, key string) (bool, error) { // bucket in object storage. func (c *ObjectStoreGRPCClient) GetObject(bucket, key string) (io.ReadCloser, error) { req := &proto.GetObjectRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Bucket: bucket, Key: key, } stream, err := c.grpcClient.GetObject(context.Background(), req) if err != nil { - return nil, fromGRPCError(err) + return nil, common.FromGRPCError(err) } receive := func() ([]byte, error) { @@ -135,7 +136,7 @@ func (c *ObjectStoreGRPCClient) GetObject(bucket, key string) (io.ReadCloser, er return nil, err } if err != nil { - return nil, fromGRPCError(err) + return nil, common.FromGRPCError(err) } return data.Data, nil @@ -143,7 +144,7 @@ func (c *ObjectStoreGRPCClient) GetObject(bucket, key string) (io.ReadCloser, er close := func() error { if err := stream.CloseSend(); err != nil { - return fromGRPCError(err) + return common.FromGRPCError(err) } return nil } @@ -156,7 +157,7 @@ func (c *ObjectStoreGRPCClient) GetObject(bucket, key string) (io.ReadCloser, er // often used to simulate a directory hierarchy in object storage). func (c *ObjectStoreGRPCClient) ListCommonPrefixes(bucket, prefix, delimiter string) ([]string, error) { req := &proto.ListCommonPrefixesRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Bucket: bucket, Prefix: prefix, Delimiter: delimiter, @@ -164,7 +165,7 @@ func (c *ObjectStoreGRPCClient) ListCommonPrefixes(bucket, prefix, delimiter str res, err := c.grpcClient.ListCommonPrefixes(context.Background(), req) if err != nil { - return nil, fromGRPCError(err) + return nil, common.FromGRPCError(err) } return res.Prefixes, nil @@ -173,14 +174,14 @@ func (c *ObjectStoreGRPCClient) ListCommonPrefixes(bucket, prefix, delimiter str // ListObjects gets a list of all objects in bucket that have the same prefix. func (c *ObjectStoreGRPCClient) ListObjects(bucket, prefix string) ([]string, error) { req := &proto.ListObjectsRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Bucket: bucket, Prefix: prefix, } res, err := c.grpcClient.ListObjects(context.Background(), req) if err != nil { - return nil, fromGRPCError(err) + return nil, common.FromGRPCError(err) } return res.Keys, nil @@ -190,13 +191,13 @@ func (c *ObjectStoreGRPCClient) ListObjects(bucket, prefix string) ([]string, er // bucket. func (c *ObjectStoreGRPCClient) DeleteObject(bucket, key string) error { req := &proto.DeleteObjectRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Bucket: bucket, Key: key, } if _, err := c.grpcClient.DeleteObject(context.Background(), req); err != nil { - return fromGRPCError(err) + return common.FromGRPCError(err) } return nil @@ -205,7 +206,7 @@ func (c *ObjectStoreGRPCClient) DeleteObject(bucket, key string) error { // CreateSignedURL creates a pre-signed URL for the given bucket and key that expires after ttl. func (c *ObjectStoreGRPCClient) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) { req := &proto.CreateSignedURLRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Bucket: bucket, Key: key, Ttl: int64(ttl), @@ -213,7 +214,7 @@ func (c *ObjectStoreGRPCClient) CreateSignedURL(bucket, key string, ttl time.Dur res, err := c.grpcClient.CreateSignedURL(context.Background(), req) if err != nil { - return "", fromGRPCError(err) + return "", common.FromGRPCError(err) } return res.Url, nil diff --git a/pkg/plugin/framework/object_store_server.go b/pkg/plugin/framework/object_store_server.go index b2f2359ce..2d3ef3658 100644 --- a/pkg/plugin/framework/object_store_server.go +++ b/pkg/plugin/framework/object_store_server.go @@ -23,6 +23,7 @@ import ( "github.com/pkg/errors" "golang.org/x/net/context" + "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" ) @@ -30,11 +31,11 @@ import ( // ObjectStoreGRPCServer implements the proto-generated ObjectStoreServer interface, and accepts // gRPC calls and forwards them to an implementation of the pluggable interface. type ObjectStoreGRPCServer struct { - mux *serverMux + mux *common.ServerMux } func (s *ObjectStoreGRPCServer) getImpl(name string) (velero.ObjectStore, error) { - impl, err := s.mux.getHandler(name) + impl, err := s.mux.GetHandler(name) if err != nil { return nil, err } @@ -52,18 +53,18 @@ func (s *ObjectStoreGRPCServer) getImpl(name string) (velero.ObjectStore, error) // cannot be initialized from the provided config. func (s *ObjectStoreGRPCServer) Init(ctx context.Context, req *proto.ObjectStoreInitRequest) (response *proto.Empty, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } if err := impl.Init(req.Config); err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.Empty{}, nil @@ -73,7 +74,7 @@ func (s *ObjectStoreGRPCServer) Init(ctx context.Context, req *proto.ObjectStore // object storage bucket with the given key. func (s *ObjectStoreGRPCServer) PutObject(stream proto.ObjectStore_PutObjectServer) (err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() @@ -82,12 +83,12 @@ func (s *ObjectStoreGRPCServer) PutObject(stream proto.ObjectStore_PutObjectServ // in our receive method, we'll use `first` on the first call firstChunk, err := stream.Recv() if err != nil { - return newGRPCError(errors.WithStack(err)) + return common.NewGRPCError(errors.WithStack(err)) } impl, err := s.getImpl(firstChunk.Plugin) if err != nil { - return newGRPCError(err) + return common.NewGRPCError(err) } bucket := firstChunk.Bucket @@ -118,11 +119,11 @@ func (s *ObjectStoreGRPCServer) PutObject(stream proto.ObjectStore_PutObjectServ } if err := impl.PutObject(bucket, key, &StreamReadCloser{receive: receive, close: close}); err != nil { - return newGRPCError(err) + return common.NewGRPCError(err) } if err := stream.SendAndClose(&proto.Empty{}); err != nil { - return newGRPCError(errors.WithStack(err)) + return common.NewGRPCError(errors.WithStack(err)) } return nil @@ -131,19 +132,19 @@ func (s *ObjectStoreGRPCServer) PutObject(stream proto.ObjectStore_PutObjectServ // ObjectExists checks if there is an object with the given key in the object storage bucket. func (s *ObjectStoreGRPCServer) ObjectExists(ctx context.Context, req *proto.ObjectExistsRequest) (response *proto.ObjectExistsResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } exists, err := impl.ObjectExists(req.Bucket, req.Key) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.ObjectExistsResponse{Exists: exists}, nil @@ -153,19 +154,19 @@ func (s *ObjectStoreGRPCServer) ObjectExists(ctx context.Context, req *proto.Obj // bucket in object storage. func (s *ObjectStoreGRPCServer) GetObject(req *proto.GetObjectRequest, stream proto.ObjectStore_GetObjectServer) (err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return newGRPCError(err) + return common.NewGRPCError(err) } rdr, err := impl.GetObject(req.Bucket, req.Key) if err != nil { - return newGRPCError(err) + return common.NewGRPCError(err) } defer rdr.Close() @@ -173,14 +174,14 @@ func (s *ObjectStoreGRPCServer) GetObject(req *proto.GetObjectRequest, stream pr for { n, err := rdr.Read(chunk) if err != nil && err != io.EOF { - return newGRPCError(errors.WithStack(err)) + return common.NewGRPCError(errors.WithStack(err)) } if n == 0 { return nil } if err := stream.Send(&proto.Bytes{Data: chunk[0:n]}); err != nil { - return newGRPCError(errors.WithStack(err)) + return common.NewGRPCError(errors.WithStack(err)) } } } @@ -190,19 +191,19 @@ func (s *ObjectStoreGRPCServer) GetObject(req *proto.GetObjectRequest, stream pr // (this is often used to simulate a directory hierarchy in object storage). func (s *ObjectStoreGRPCServer) ListCommonPrefixes(ctx context.Context, req *proto.ListCommonPrefixesRequest) (response *proto.ListCommonPrefixesResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } prefixes, err := impl.ListCommonPrefixes(req.Bucket, req.Prefix, req.Delimiter) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.ListCommonPrefixesResponse{Prefixes: prefixes}, nil @@ -211,19 +212,19 @@ func (s *ObjectStoreGRPCServer) ListCommonPrefixes(ctx context.Context, req *pro // ListObjects gets a list of all objects in bucket that have the same prefix. func (s *ObjectStoreGRPCServer) ListObjects(ctx context.Context, req *proto.ListObjectsRequest) (response *proto.ListObjectsResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } keys, err := impl.ListObjects(req.Bucket, req.Prefix) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.ListObjectsResponse{Keys: keys}, nil @@ -233,18 +234,18 @@ func (s *ObjectStoreGRPCServer) ListObjects(ctx context.Context, req *proto.List // bucket. func (s *ObjectStoreGRPCServer) DeleteObject(ctx context.Context, req *proto.DeleteObjectRequest) (response *proto.Empty, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } if err := impl.DeleteObject(req.Bucket, req.Key); err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.Empty{}, nil @@ -253,19 +254,19 @@ func (s *ObjectStoreGRPCServer) DeleteObject(ctx context.Context, req *proto.Del // CreateSignedURL creates a pre-signed URL for the given bucket and key that expires after ttl. func (s *ObjectStoreGRPCServer) CreateSignedURL(ctx context.Context, req *proto.CreateSignedURLRequest) (response *proto.CreateSignedURLResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } url, err := impl.CreateSignedURL(req.Bucket, req.Key, time.Duration(req.Ttl)) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.CreateSignedURLResponse{Url: url}, nil diff --git a/pkg/plugin/framework/plugin_lister.go b/pkg/plugin/framework/plugin_lister.go index aed7de77d..e658ae8a2 100644 --- a/pkg/plugin/framework/plugin_lister.go +++ b/pkg/plugin/framework/plugin_lister.go @@ -22,13 +22,14 @@ import ( "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" ) // PluginIdentifier uniquely identifies a plugin by command, kind, and name. type PluginIdentifier struct { Command string - Kind PluginKind + Kind common.PluginKind Name string } @@ -87,13 +88,13 @@ func (c *PluginListerGRPCClient) ListPlugins() ([]PluginIdentifier, error) { ret := make([]PluginIdentifier, len(resp.Plugins)) for i, id := range resp.Plugins { - if _, ok := AllPluginKinds()[id.Kind]; !ok { + if _, ok := common.AllPluginKinds()[id.Kind]; !ok { return nil, errors.Errorf("invalid plugin kind: %s", id.Kind) } ret[i] = PluginIdentifier{ Command: id.Command, - Kind: PluginKind(id.Kind), + Kind: common.PluginKind(id.Kind), Name: id.Name, } } @@ -126,7 +127,7 @@ func (s *PluginListerGRPCServer) ListPlugins(ctx context.Context, req *proto.Emp plugins := make([]*proto.PluginIdentifier, len(list)) for i, id := range list { - if _, ok := AllPluginKinds()[id.Kind.String()]; !ok { + if _, ok := common.AllPluginKinds()[id.Kind.String()]; !ok { return nil, errors.Errorf("invalid plugin kind: %s", id.Kind) } diff --git a/pkg/plugin/framework/restore_item_action.go b/pkg/plugin/framework/restore_item_action.go index 255c67ae8..b5a3d41c1 100644 --- a/pkg/plugin/framework/restore_item_action.go +++ b/pkg/plugin/framework/restore_item_action.go @@ -21,6 +21,7 @@ import ( "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" ) @@ -29,16 +30,16 @@ import ( // interface. type RestoreItemActionPlugin struct { plugin.NetRPCUnsupportedPlugin - *pluginBase + *common.PluginBase } // GRPCClient returns a RestoreItemAction gRPC client. func (p *RestoreItemActionPlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, clientConn *grpc.ClientConn) (interface{}, error) { - return newClientDispenser(p.clientLogger, clientConn, newRestoreItemActionGRPCClient), nil + return common.NewClientDispenser(p.ClientLogger, clientConn, newRestoreItemActionGRPCClient), nil } // GRPCServer registers a RestoreItemAction gRPC server. func (p *RestoreItemActionPlugin) GRPCServer(_ *plugin.GRPCBroker, server *grpc.Server) error { - proto.RegisterRestoreItemActionServer(server, &RestoreItemActionGRPCServer{mux: p.serverMux}) + proto.RegisterRestoreItemActionServer(server, &RestoreItemActionGRPCServer{mux: p.ServerMux}) return nil } diff --git a/pkg/plugin/framework/restore_item_action_client.go b/pkg/plugin/framework/restore_item_action_client.go index 33d7fff3a..03907f390 100644 --- a/pkg/plugin/framework/restore_item_action_client.go +++ b/pkg/plugin/framework/restore_item_action_client.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + "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" ) @@ -32,30 +33,30 @@ import ( var _ velero.RestoreItemAction = &RestoreItemActionGRPCClient{} // NewRestoreItemActionPlugin constructs a RestoreItemActionPlugin. -func NewRestoreItemActionPlugin(options ...PluginOption) *RestoreItemActionPlugin { +func NewRestoreItemActionPlugin(options ...common.PluginOption) *RestoreItemActionPlugin { return &RestoreItemActionPlugin{ - pluginBase: newPluginBase(options...), + PluginBase: common.NewPluginBase(options...), } } // RestoreItemActionGRPCClient implements the backup/ItemAction interface and uses a // gRPC client to make calls to the plugin server. type RestoreItemActionGRPCClient struct { - *clientBase + *common.ClientBase grpcClient proto.RestoreItemActionClient } -func newRestoreItemActionGRPCClient(base *clientBase, clientConn *grpc.ClientConn) interface{} { +func newRestoreItemActionGRPCClient(base *common.ClientBase, clientConn *grpc.ClientConn) interface{} { return &RestoreItemActionGRPCClient{ - clientBase: base, + ClientBase: base, grpcClient: proto.NewRestoreItemActionClient(clientConn), } } func (c *RestoreItemActionGRPCClient) AppliesTo() (velero.ResourceSelector, error) { - res, err := c.grpcClient.AppliesTo(context.Background(), &proto.RestoreItemActionAppliesToRequest{Plugin: c.plugin}) + res, err := c.grpcClient.AppliesTo(context.Background(), &proto.RestoreItemActionAppliesToRequest{Plugin: c.Plugin}) if err != nil { - return velero.ResourceSelector{}, fromGRPCError(err) + return velero.ResourceSelector{}, common.FromGRPCError(err) } if res.ResourceSelector == nil { @@ -88,7 +89,7 @@ func (c *RestoreItemActionGRPCClient) Execute(input *velero.RestoreItemActionExe } req := &proto.RestoreItemActionExecuteRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Item: itemJSON, ItemFromBackup: itemFromBackupJSON, Restore: restoreJSON, @@ -96,7 +97,7 @@ func (c *RestoreItemActionGRPCClient) Execute(input *velero.RestoreItemActionExe res, err := c.grpcClient.Execute(context.Background(), req) if err != nil { - return nil, fromGRPCError(err) + return nil, common.FromGRPCError(err) } var updatedItem unstructured.Unstructured diff --git a/pkg/plugin/framework/restore_item_action_server.go b/pkg/plugin/framework/restore_item_action_server.go index ae5affb15..5b45f4e91 100644 --- a/pkg/plugin/framework/restore_item_action_server.go +++ b/pkg/plugin/framework/restore_item_action_server.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "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" ) @@ -31,11 +32,11 @@ import ( // RestoreItemActionGRPCServer implements the proto-generated RestoreItemActionServer interface, and accepts // gRPC calls and forwards them to an implementation of the pluggable interface. type RestoreItemActionGRPCServer struct { - mux *serverMux + mux *common.ServerMux } func (s *RestoreItemActionGRPCServer) getImpl(name string) (velero.RestoreItemAction, error) { - impl, err := s.mux.getHandler(name) + impl, err := s.mux.GetHandler(name) if err != nil { return nil, err } @@ -50,19 +51,19 @@ func (s *RestoreItemActionGRPCServer) getImpl(name string) (velero.RestoreItemAc func (s *RestoreItemActionGRPCServer) AppliesTo(ctx context.Context, req *proto.RestoreItemActionAppliesToRequest) (response *proto.RestoreItemActionAppliesToResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } resourceSelector, err := impl.AppliesTo() if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.RestoreItemActionAppliesToResponse{ @@ -78,14 +79,14 @@ func (s *RestoreItemActionGRPCServer) AppliesTo(ctx context.Context, req *proto. func (s *RestoreItemActionGRPCServer) Execute(ctx context.Context, req *proto.RestoreItemActionExecuteRequest) (response *proto.RestoreItemActionExecuteResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var ( @@ -95,15 +96,15 @@ func (s *RestoreItemActionGRPCServer) Execute(ctx context.Context, req *proto.Re ) if err := json.Unmarshal(req.Item, &item); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } if err := json.Unmarshal(req.ItemFromBackup, &itemFromBackup); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } if err := json.Unmarshal(req.Restore, &restoreObj); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } executeOutput, err := impl.Execute(&velero.RestoreItemActionExecuteInput{ @@ -112,7 +113,7 @@ func (s *RestoreItemActionGRPCServer) Execute(ctx context.Context, req *proto.Re Restore: &restoreObj, }) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } // If the plugin implementation returned a nil updateItem (meaning no modifications), reset updatedItem to the @@ -123,7 +124,7 @@ func (s *RestoreItemActionGRPCServer) Execute(ctx context.Context, req *proto.Re } else { updatedItemJSON, err = json.Marshal(executeOutput.UpdatedItem.UnstructuredContent()) if err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } } diff --git a/pkg/plugin/framework/server.go b/pkg/plugin/framework/server.go index b25ef341d..20c5e48e0 100644 --- a/pkg/plugin/framework/server.go +++ b/pkg/plugin/framework/server.go @@ -25,6 +25,7 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/pflag" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/util/logging" ) @@ -40,43 +41,43 @@ type Server interface { // RegisterBackupItemAction registers a backup item action. Accepted format // for the plugin name is /. - RegisterBackupItemAction(pluginName string, initializer HandlerInitializer) Server + RegisterBackupItemAction(pluginName string, initializer common.HandlerInitializer) Server // RegisterBackupItemActions registers multiple backup item actions. - RegisterBackupItemActions(map[string]HandlerInitializer) Server + RegisterBackupItemActions(map[string]common.HandlerInitializer) Server // RegisterVolumeSnapshotter registers a volume snapshotter. Accepted format // for the plugin name is /. - RegisterVolumeSnapshotter(pluginName string, initializer HandlerInitializer) Server + RegisterVolumeSnapshotter(pluginName string, initializer common.HandlerInitializer) Server // RegisterVolumeSnapshotters registers multiple volume snapshotters. - RegisterVolumeSnapshotters(map[string]HandlerInitializer) Server + RegisterVolumeSnapshotters(map[string]common.HandlerInitializer) Server // RegisterObjectStore registers an object store. Accepted format // for the plugin name is /. - RegisterObjectStore(pluginName string, initializer HandlerInitializer) Server + RegisterObjectStore(pluginName string, initializer common.HandlerInitializer) Server // RegisterObjectStores registers multiple object stores. - RegisterObjectStores(map[string]HandlerInitializer) Server + RegisterObjectStores(map[string]common.HandlerInitializer) Server // RegisterRestoreItemAction registers a restore item action. Accepted format // for the plugin name is /. - RegisterRestoreItemAction(pluginName string, initializer HandlerInitializer) Server + RegisterRestoreItemAction(pluginName string, initializer common.HandlerInitializer) Server // RegisterRestoreItemActions registers multiple restore item actions. - RegisterRestoreItemActions(map[string]HandlerInitializer) Server + RegisterRestoreItemActions(map[string]common.HandlerInitializer) Server // RegisterDeleteItemAction registers a delete item action. Accepted format // for the plugin name is /. - RegisterDeleteItemAction(pluginName string, initializer HandlerInitializer) Server + RegisterDeleteItemAction(pluginName string, initializer common.HandlerInitializer) Server // RegisterDeleteItemActions registers multiple Delete item actions. - RegisterDeleteItemActions(map[string]HandlerInitializer) Server + RegisterDeleteItemActions(map[string]common.HandlerInitializer) Server - RegisterItemSnapshotter(pluginName string, initializer HandlerInitializer) Server + RegisterItemSnapshotter(pluginName string, initializer common.HandlerInitializer) Server // RegisterItemSnapshotters registers multiple Item Snapshotters - RegisterItemSnapshotters(map[string]HandlerInitializer) Server + RegisterItemSnapshotters(map[string]common.HandlerInitializer) Server // Server runs the plugin server. Serve() @@ -102,12 +103,12 @@ func NewServer() Server { return &server{ log: log, logLevelFlag: logging.LogLevelFlag(log.Level), - backupItemAction: NewBackupItemActionPlugin(serverLogger(log)), - volumeSnapshotter: NewVolumeSnapshotterPlugin(serverLogger(log)), - objectStore: NewObjectStorePlugin(serverLogger(log)), - restoreItemAction: NewRestoreItemActionPlugin(serverLogger(log)), - deleteItemAction: NewDeleteItemActionPlugin(serverLogger(log)), - itemSnapshotter: NewItemSnapshotterPlugin(serverLogger(log)), + backupItemAction: NewBackupItemActionPlugin(common.ServerLogger(log)), + volumeSnapshotter: NewVolumeSnapshotterPlugin(common.ServerLogger(log)), + objectStore: NewObjectStorePlugin(common.ServerLogger(log)), + restoreItemAction: NewRestoreItemActionPlugin(common.ServerLogger(log)), + deleteItemAction: NewDeleteItemActionPlugin(common.ServerLogger(log)), + itemSnapshotter: NewItemSnapshotterPlugin(common.ServerLogger(log)), } } @@ -119,71 +120,71 @@ func (s *server) BindFlags(flags *pflag.FlagSet) Server { return s } -func (s *server) RegisterBackupItemAction(name string, initializer HandlerInitializer) Server { - s.backupItemAction.register(name, initializer) +func (s *server) RegisterBackupItemAction(name string, initializer common.HandlerInitializer) Server { + s.backupItemAction.Register(name, initializer) return s } -func (s *server) RegisterBackupItemActions(m map[string]HandlerInitializer) Server { +func (s *server) RegisterBackupItemActions(m map[string]common.HandlerInitializer) Server { for name := range m { s.RegisterBackupItemAction(name, m[name]) } return s } -func (s *server) RegisterVolumeSnapshotter(name string, initializer HandlerInitializer) Server { - s.volumeSnapshotter.register(name, initializer) +func (s *server) RegisterVolumeSnapshotter(name string, initializer common.HandlerInitializer) Server { + s.volumeSnapshotter.Register(name, initializer) return s } -func (s *server) RegisterVolumeSnapshotters(m map[string]HandlerInitializer) Server { +func (s *server) RegisterVolumeSnapshotters(m map[string]common.HandlerInitializer) Server { for name := range m { s.RegisterVolumeSnapshotter(name, m[name]) } return s } -func (s *server) RegisterObjectStore(name string, initializer HandlerInitializer) Server { - s.objectStore.register(name, initializer) +func (s *server) RegisterObjectStore(name string, initializer common.HandlerInitializer) Server { + s.objectStore.Register(name, initializer) return s } -func (s *server) RegisterObjectStores(m map[string]HandlerInitializer) Server { +func (s *server) RegisterObjectStores(m map[string]common.HandlerInitializer) Server { for name := range m { s.RegisterObjectStore(name, m[name]) } return s } -func (s *server) RegisterRestoreItemAction(name string, initializer HandlerInitializer) Server { - s.restoreItemAction.register(name, initializer) +func (s *server) RegisterRestoreItemAction(name string, initializer common.HandlerInitializer) Server { + s.restoreItemAction.Register(name, initializer) return s } -func (s *server) RegisterRestoreItemActions(m map[string]HandlerInitializer) Server { +func (s *server) RegisterRestoreItemActions(m map[string]common.HandlerInitializer) Server { for name := range m { s.RegisterRestoreItemAction(name, m[name]) } return s } -func (s *server) RegisterDeleteItemAction(name string, initializer HandlerInitializer) Server { - s.deleteItemAction.register(name, initializer) +func (s *server) RegisterDeleteItemAction(name string, initializer common.HandlerInitializer) Server { + s.deleteItemAction.Register(name, initializer) return s } -func (s *server) RegisterDeleteItemActions(m map[string]HandlerInitializer) Server { +func (s *server) RegisterDeleteItemActions(m map[string]common.HandlerInitializer) Server { for name := range m { s.RegisterDeleteItemAction(name, m[name]) } return s } -func (s *server) RegisterItemSnapshotter(name string, initializer HandlerInitializer) Server { - s.itemSnapshotter.register(name, initializer) +func (s *server) RegisterItemSnapshotter(name string, initializer common.HandlerInitializer) Server { + s.itemSnapshotter.Register(name, initializer) return s } -func (s *server) RegisterItemSnapshotters(m map[string]HandlerInitializer) Server { +func (s *server) RegisterItemSnapshotters(m map[string]common.HandlerInitializer) Server { for name := range m { s.RegisterItemSnapshotter(name, m[name]) } @@ -191,10 +192,10 @@ func (s *server) RegisterItemSnapshotters(m map[string]HandlerInitializer) Serve } // getNames returns a list of PluginIdentifiers registered with plugin. -func getNames(command string, kind PluginKind, plugin Interface) []PluginIdentifier { +func getNames(command string, kind common.PluginKind, plugin Interface) []PluginIdentifier { var pluginIdentifiers []PluginIdentifier - for _, name := range plugin.names() { + for _, name := range plugin.Names() { id := PluginIdentifier{Command: command, Kind: kind, Name: name} pluginIdentifiers = append(pluginIdentifiers, id) } @@ -214,25 +215,25 @@ func (s *server) Serve() { command := os.Args[0] var pluginIdentifiers []PluginIdentifier - pluginIdentifiers = append(pluginIdentifiers, getNames(command, PluginKindBackupItemAction, s.backupItemAction)...) - pluginIdentifiers = append(pluginIdentifiers, getNames(command, PluginKindVolumeSnapshotter, s.volumeSnapshotter)...) - pluginIdentifiers = append(pluginIdentifiers, getNames(command, PluginKindObjectStore, s.objectStore)...) - pluginIdentifiers = append(pluginIdentifiers, getNames(command, PluginKindRestoreItemAction, s.restoreItemAction)...) - pluginIdentifiers = append(pluginIdentifiers, getNames(command, PluginKindDeleteItemAction, s.deleteItemAction)...) - pluginIdentifiers = append(pluginIdentifiers, getNames(command, PluginKindItemSnapshotter, s.itemSnapshotter)...) + pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindBackupItemAction, s.backupItemAction)...) + pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindVolumeSnapshotter, s.volumeSnapshotter)...) + pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindObjectStore, s.objectStore)...) + pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindRestoreItemAction, s.restoreItemAction)...) + pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindDeleteItemAction, s.deleteItemAction)...) + pluginIdentifiers = append(pluginIdentifiers, getNames(command, common.PluginKindItemSnapshotter, s.itemSnapshotter)...) pluginLister := NewPluginLister(pluginIdentifiers...) plugin.Serve(&plugin.ServeConfig{ HandshakeConfig: Handshake(), Plugins: map[string]plugin.Plugin{ - string(PluginKindBackupItemAction): s.backupItemAction, - string(PluginKindVolumeSnapshotter): s.volumeSnapshotter, - string(PluginKindObjectStore): s.objectStore, - string(PluginKindPluginLister): NewPluginListerPlugin(pluginLister), - string(PluginKindRestoreItemAction): s.restoreItemAction, - string(PluginKindDeleteItemAction): s.deleteItemAction, - string(PluginKindItemSnapshotter): s.itemSnapshotter, + string(common.PluginKindBackupItemAction): s.backupItemAction, + string(common.PluginKindVolumeSnapshotter): s.volumeSnapshotter, + string(common.PluginKindObjectStore): s.objectStore, + string(common.PluginKindPluginLister): NewPluginListerPlugin(pluginLister), + string(common.PluginKindRestoreItemAction): s.restoreItemAction, + string(common.PluginKindDeleteItemAction): s.deleteItemAction, + string(common.PluginKindItemSnapshotter): s.itemSnapshotter, }, GRPCServer: plugin.DefaultGRPCServer, }) diff --git a/pkg/plugin/framework/volume_snapshotter.go b/pkg/plugin/framework/volume_snapshotter.go index 50602b2c0..566fc1eb7 100644 --- a/pkg/plugin/framework/volume_snapshotter.go +++ b/pkg/plugin/framework/volume_snapshotter.go @@ -21,6 +21,7 @@ import ( "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" ) @@ -29,16 +30,16 @@ import ( // interface. type VolumeSnapshotterPlugin struct { plugin.NetRPCUnsupportedPlugin - *pluginBase + *common.PluginBase } // GRPCClient returns a VolumeSnapshotter gRPC client. func (p *VolumeSnapshotterPlugin) GRPCClient(_ context.Context, _ *plugin.GRPCBroker, clientConn *grpc.ClientConn) (interface{}, error) { - return newClientDispenser(p.clientLogger, clientConn, newVolumeSnapshotterGRPCClient), nil + return common.NewClientDispenser(p.ClientLogger, clientConn, newVolumeSnapshotterGRPCClient), nil } // GRPCServer registers a VolumeSnapshotter gRPC server. func (p *VolumeSnapshotterPlugin) GRPCServer(_ *plugin.GRPCBroker, server *grpc.Server) error { - proto.RegisterVolumeSnapshotterServer(server, &VolumeSnapshotterGRPCServer{mux: p.serverMux}) + proto.RegisterVolumeSnapshotterServer(server, &VolumeSnapshotterGRPCServer{mux: p.ServerMux}) return nil } diff --git a/pkg/plugin/framework/volume_snapshotter_client.go b/pkg/plugin/framework/volume_snapshotter_client.go index 53ac58d25..a35904617 100644 --- a/pkg/plugin/framework/volume_snapshotter_client.go +++ b/pkg/plugin/framework/volume_snapshotter_client.go @@ -25,26 +25,27 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" proto "github.com/vmware-tanzu/velero/pkg/plugin/generated" ) // NewVolumeSnapshotterPlugin constructs a VolumeSnapshotterPlugin. -func NewVolumeSnapshotterPlugin(options ...PluginOption) *VolumeSnapshotterPlugin { +func NewVolumeSnapshotterPlugin(options ...common.PluginOption) *VolumeSnapshotterPlugin { return &VolumeSnapshotterPlugin{ - pluginBase: newPluginBase(options...), + PluginBase: common.NewPluginBase(options...), } } // VolumeSnapshotterGRPCClient implements the cloudprovider.VolumeSnapshotter interface and uses a // gRPC client to make calls to the plugin server. type VolumeSnapshotterGRPCClient struct { - *clientBase + *common.ClientBase grpcClient proto.VolumeSnapshotterClient } -func newVolumeSnapshotterGRPCClient(base *clientBase, clientConn *grpc.ClientConn) interface{} { +func newVolumeSnapshotterGRPCClient(base *common.ClientBase, clientConn *grpc.ClientConn) interface{} { return &VolumeSnapshotterGRPCClient{ - clientBase: base, + ClientBase: base, grpcClient: proto.NewVolumeSnapshotterClient(clientConn), } } @@ -54,12 +55,12 @@ func newVolumeSnapshotterGRPCClient(base *clientBase, clientConn *grpc.ClientCon // cannot be initialized from the provided config. func (c *VolumeSnapshotterGRPCClient) Init(config map[string]string) error { req := &proto.VolumeSnapshotterInitRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, Config: config, } if _, err := c.grpcClient.Init(context.Background(), req); err != nil { - return fromGRPCError(err) + return common.FromGRPCError(err) } return nil @@ -69,7 +70,7 @@ func (c *VolumeSnapshotterGRPCClient) Init(config map[string]string) error { // and with the specified type and IOPS (if using provisioned IOPS). func (c *VolumeSnapshotterGRPCClient) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (string, error) { req := &proto.CreateVolumeRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, SnapshotID: snapshotID, VolumeType: volumeType, VolumeAZ: volumeAZ, @@ -83,7 +84,7 @@ func (c *VolumeSnapshotterGRPCClient) CreateVolumeFromSnapshot(snapshotID, volum res, err := c.grpcClient.CreateVolumeFromSnapshot(context.Background(), req) if err != nil { - return "", fromGRPCError(err) + return "", common.FromGRPCError(err) } return res.VolumeID, nil @@ -93,14 +94,14 @@ func (c *VolumeSnapshotterGRPCClient) CreateVolumeFromSnapshot(snapshotID, volum // volume. func (c *VolumeSnapshotterGRPCClient) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) { req := &proto.GetVolumeInfoRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, VolumeID: volumeID, VolumeAZ: volumeAZ, } res, err := c.grpcClient.GetVolumeInfo(context.Background(), req) if err != nil { - return "", nil, fromGRPCError(err) + return "", nil, common.FromGRPCError(err) } var iops *int64 @@ -115,7 +116,7 @@ func (c *VolumeSnapshotterGRPCClient) GetVolumeInfo(volumeID, volumeAZ string) ( // set of tags to the snapshot. func (c *VolumeSnapshotterGRPCClient) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) { req := &proto.CreateSnapshotRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, VolumeID: volumeID, VolumeAZ: volumeAZ, Tags: tags, @@ -123,7 +124,7 @@ func (c *VolumeSnapshotterGRPCClient) CreateSnapshot(volumeID, volumeAZ string, res, err := c.grpcClient.CreateSnapshot(context.Background(), req) if err != nil { - return "", fromGRPCError(err) + return "", common.FromGRPCError(err) } return res.SnapshotID, nil @@ -132,12 +133,12 @@ func (c *VolumeSnapshotterGRPCClient) CreateSnapshot(volumeID, volumeAZ string, // DeleteSnapshot deletes the specified volume snapshot. func (c *VolumeSnapshotterGRPCClient) DeleteSnapshot(snapshotID string) error { req := &proto.DeleteSnapshotRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, SnapshotID: snapshotID, } if _, err := c.grpcClient.DeleteSnapshot(context.Background(), req); err != nil { - return fromGRPCError(err) + return common.FromGRPCError(err) } return nil @@ -150,13 +151,13 @@ func (c *VolumeSnapshotterGRPCClient) GetVolumeID(pv runtime.Unstructured) (stri } req := &proto.GetVolumeIDRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, PersistentVolume: encodedPV, } resp, err := c.grpcClient.GetVolumeID(context.Background(), req) if err != nil { - return "", fromGRPCError(err) + return "", common.FromGRPCError(err) } return resp.VolumeID, nil @@ -169,14 +170,14 @@ func (c *VolumeSnapshotterGRPCClient) SetVolumeID(pv runtime.Unstructured, volum } req := &proto.SetVolumeIDRequest{ - Plugin: c.plugin, + Plugin: c.Plugin, PersistentVolume: encodedPV, VolumeID: volumeID, } resp, err := c.grpcClient.SetVolumeID(context.Background(), req) if err != nil { - return nil, fromGRPCError(err) + return nil, common.FromGRPCError(err) } var updatedPV unstructured.Unstructured diff --git a/pkg/plugin/framework/volume_snapshotter_server.go b/pkg/plugin/framework/volume_snapshotter_server.go index bde371c93..e0073db9a 100644 --- a/pkg/plugin/framework/volume_snapshotter_server.go +++ b/pkg/plugin/framework/volume_snapshotter_server.go @@ -23,6 +23,7 @@ import ( "golang.org/x/net/context" "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" ) @@ -30,11 +31,11 @@ import ( // VolumeSnapshotterGRPCServer implements the proto-generated VolumeSnapshotterServer interface, and accepts // gRPC calls and forwards them to an implementation of the pluggable interface. type VolumeSnapshotterGRPCServer struct { - mux *serverMux + mux *common.ServerMux } func (s *VolumeSnapshotterGRPCServer) getImpl(name string) (velero.VolumeSnapshotter, error) { - impl, err := s.mux.getHandler(name) + impl, err := s.mux.GetHandler(name) if err != nil { return nil, err } @@ -52,18 +53,18 @@ func (s *VolumeSnapshotterGRPCServer) getImpl(name string) (velero.VolumeSnapsho // cannot be initialized from the provided config. func (s *VolumeSnapshotterGRPCServer) Init(ctx context.Context, req *proto.VolumeSnapshotterInitRequest) (response *proto.Empty, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } if err := impl.Init(req.Config); err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.Empty{}, nil @@ -73,14 +74,14 @@ func (s *VolumeSnapshotterGRPCServer) Init(ctx context.Context, req *proto.Volum // and with the specified type and IOPS (if using provisioned IOPS). func (s *VolumeSnapshotterGRPCServer) CreateVolumeFromSnapshot(ctx context.Context, req *proto.CreateVolumeRequest) (response *proto.CreateVolumeResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } snapshotID := req.SnapshotID @@ -94,7 +95,7 @@ func (s *VolumeSnapshotterGRPCServer) CreateVolumeFromSnapshot(ctx context.Conte volumeID, err := impl.CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ, iops) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.CreateVolumeResponse{VolumeID: volumeID}, nil @@ -104,19 +105,19 @@ func (s *VolumeSnapshotterGRPCServer) CreateVolumeFromSnapshot(ctx context.Conte // volume. func (s *VolumeSnapshotterGRPCServer) GetVolumeInfo(ctx context.Context, req *proto.GetVolumeInfoRequest) (response *proto.GetVolumeInfoResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } volumeType, iops, err := impl.GetVolumeInfo(req.VolumeID, req.VolumeAZ) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } res := &proto.GetVolumeInfoResponse{ @@ -134,19 +135,19 @@ func (s *VolumeSnapshotterGRPCServer) GetVolumeInfo(ctx context.Context, req *pr // set of tags to the snapshot. func (s *VolumeSnapshotterGRPCServer) CreateSnapshot(ctx context.Context, req *proto.CreateSnapshotRequest) (response *proto.CreateSnapshotResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } snapshotID, err := impl.CreateSnapshot(req.VolumeID, req.VolumeAZ, req.Tags) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.CreateSnapshotResponse{SnapshotID: snapshotID}, nil @@ -155,18 +156,18 @@ func (s *VolumeSnapshotterGRPCServer) CreateSnapshot(ctx context.Context, req *p // DeleteSnapshot deletes the specified volume snapshot. func (s *VolumeSnapshotterGRPCServer) DeleteSnapshot(ctx context.Context, req *proto.DeleteSnapshotRequest) (response *proto.Empty, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } if err := impl.DeleteSnapshot(req.SnapshotID); err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.Empty{}, nil @@ -174,25 +175,25 @@ func (s *VolumeSnapshotterGRPCServer) DeleteSnapshot(ctx context.Context, req *p func (s *VolumeSnapshotterGRPCServer) GetVolumeID(ctx context.Context, req *proto.GetVolumeIDRequest) (response *proto.GetVolumeIDResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var pv unstructured.Unstructured if err := json.Unmarshal(req.PersistentVolume, &pv); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } volumeID, err := impl.GetVolumeID(&pv) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.GetVolumeIDResponse{VolumeID: volumeID}, nil @@ -200,29 +201,29 @@ func (s *VolumeSnapshotterGRPCServer) GetVolumeID(ctx context.Context, req *prot func (s *VolumeSnapshotterGRPCServer) SetVolumeID(ctx context.Context, req *proto.SetVolumeIDRequest) (response *proto.SetVolumeIDResponse, err error) { defer func() { - if recoveredErr := handlePanic(recover()); recoveredErr != nil { + if recoveredErr := common.HandlePanic(recover()); recoveredErr != nil { err = recoveredErr } }() impl, err := s.getImpl(req.Plugin) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } var pv unstructured.Unstructured if err := json.Unmarshal(req.PersistentVolume, &pv); err != nil { - return nil, newGRPCError(errors.WithStack(err)) + return nil, common.NewGRPCError(errors.WithStack(err)) } updatedPV, err := impl.SetVolumeID(&pv, req.VolumeID) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } updatedPVBytes, err := json.Marshal(updatedPV.UnstructuredContent()) if err != nil { - return nil, newGRPCError(err) + return nil, common.NewGRPCError(err) } return &proto.SetVolumeIDResponse{PersistentVolume: updatedPVBytes}, nil diff --git a/pkg/backup/mocks/item_action.go b/pkg/plugin/velero/mocks/backupitemaction/v1/BackupItemAction.go similarity index 58% rename from pkg/backup/mocks/item_action.go rename to pkg/plugin/velero/mocks/backupitemaction/v1/BackupItemAction.go index 5d4bd8db5..cfca2ef6d 100644 --- a/pkg/backup/mocks/item_action.go +++ b/pkg/plugin/velero/mocks/backupitemaction/v1/BackupItemAction.go @@ -1,5 +1,5 @@ /* -Copyright 2018 the Velero contributors. +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. @@ -14,23 +14,25 @@ See the License for the specific language governing permissions and limitations under the License. */ // Code generated by mockery v1.0.0. DO NOT EDIT. -package mocks + +package v1 import ( mock "github.com/stretchr/testify/mock" runtime "k8s.io/apimachinery/pkg/runtime" - v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - "github.com/vmware-tanzu/velero/pkg/plugin/velero" + velero "github.com/vmware-tanzu/velero/pkg/plugin/velero" + + velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" ) -// ItemAction is an autogenerated mock type for the ItemAction type -type ItemAction struct { +// BackupItemAction is an autogenerated mock type for the BackupItemAction type +type BackupItemAction struct { mock.Mock } // AppliesTo provides a mock function with given fields: -func (_m *ItemAction) AppliesTo() (velero.ResourceSelector, error) { +func (_m *BackupItemAction) AppliesTo() (velero.ResourceSelector, error) { ret := _m.Called() var r0 velero.ResourceSelector @@ -50,13 +52,13 @@ func (_m *ItemAction) AppliesTo() (velero.ResourceSelector, error) { return r0, r1 } -// Execute provides a mock function with given fields: item, _a1 -func (_m *ItemAction) Execute(item runtime.Unstructured, _a1 *v1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) { - ret := _m.Called(item, _a1) +// Execute provides a mock function with given fields: item, backup +func (_m *BackupItemAction) Execute(item runtime.Unstructured, backup *velerov1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) { + ret := _m.Called(item, backup) var r0 runtime.Unstructured - if rf, ok := ret.Get(0).(func(runtime.Unstructured, *v1.Backup) runtime.Unstructured); ok { - r0 = rf(item, _a1) + if rf, ok := ret.Get(0).(func(runtime.Unstructured, *velerov1.Backup) runtime.Unstructured); ok { + r0 = rf(item, backup) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(runtime.Unstructured) @@ -64,8 +66,8 @@ func (_m *ItemAction) Execute(item runtime.Unstructured, _a1 *v1.Backup) (runtim } var r1 []velero.ResourceIdentifier - if rf, ok := ret.Get(1).(func(runtime.Unstructured, *v1.Backup) []velero.ResourceIdentifier); ok { - r1 = rf(item, _a1) + if rf, ok := ret.Get(1).(func(runtime.Unstructured, *velerov1.Backup) []velero.ResourceIdentifier); ok { + r1 = rf(item, backup) } else { if ret.Get(1) != nil { r1 = ret.Get(1).([]velero.ResourceIdentifier) @@ -73,8 +75,8 @@ func (_m *ItemAction) Execute(item runtime.Unstructured, _a1 *v1.Backup) (runtim } var r2 error - if rf, ok := ret.Get(2).(func(runtime.Unstructured, *v1.Backup) error); ok { - r2 = rf(item, _a1) + if rf, ok := ret.Get(2).(func(runtime.Unstructured, *velerov1.Backup) error); ok { + r2 = rf(item, backup) } else { r2 = ret.Error(2) } diff --git a/pkg/restore/change_pvc_node_selector.go b/pkg/restore/change_pvc_node_selector.go index b4d947c21..d281d318f 100644 --- a/pkg/restore/change_pvc_node_selector.go +++ b/pkg/restore/change_pvc_node_selector.go @@ -26,7 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" corev1client "k8s.io/client-go/kubernetes/typed/core/v1" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -130,7 +130,7 @@ func (p *ChangePVCNodeSelectorAction) Execute(input *velero.RestoreItemActionExe func getNewNodeFromConfigMap(client corev1client.ConfigMapInterface, node string) (string, error) { // fetch node mapping from configMap - config, err := getPluginConfig(framework.PluginKindRestoreItemAction, "velero.io/change-pvc-node-selector", client) + config, err := getPluginConfig(common.PluginKindRestoreItemAction, "velero.io/change-pvc-node-selector", client) if err != nil { return "", err } diff --git a/pkg/restore/change_storageclass_action.go b/pkg/restore/change_storageclass_action.go index 577ab28ec..a02b7c484 100644 --- a/pkg/restore/change_storageclass_action.go +++ b/pkg/restore/change_storageclass_action.go @@ -29,7 +29,7 @@ import ( corev1client "k8s.io/client-go/kubernetes/typed/core/v1" storagev1client "k8s.io/client-go/kubernetes/typed/storage/v1" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -69,7 +69,7 @@ func (a *ChangeStorageClassAction) Execute(input *velero.RestoreItemActionExecut defer a.logger.Info("Done executing ChangeStorageClassAction") a.logger.Debug("Getting plugin config") - config, err := getPluginConfig(framework.PluginKindRestoreItemAction, "velero.io/change-storage-class", a.configMapClient) + config, err := getPluginConfig(common.PluginKindRestoreItemAction, "velero.io/change-storage-class", a.configMapClient) if err != nil { return nil, err } diff --git a/pkg/restore/restic_restore_action.go b/pkg/restore/restic_restore_action.go index 586dbf785..f2d8df9a1 100644 --- a/pkg/restore/restic_restore_action.go +++ b/pkg/restore/restic_restore_action.go @@ -34,7 +34,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/builder" velerov1client "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1" "github.com/vmware-tanzu/velero/pkg/label" - "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/framework/common" "github.com/vmware-tanzu/velero/pkg/plugin/velero" "github.com/vmware-tanzu/velero/pkg/podvolume" "github.com/vmware-tanzu/velero/pkg/util/kube" @@ -107,7 +107,7 @@ func (a *ResticRestoreAction) Execute(input *velero.RestoreItemActionExecuteInpu // TODO we might want/need to get plugin config at the top of this method at some point; for now, wait // until we know we're doing a restore before getting config. log.Debugf("Getting plugin config") - config, err := getPluginConfig(framework.PluginKindRestoreItemAction, "velero.io/restic", a.client) + config, err := getPluginConfig(common.PluginKindRestoreItemAction, "velero.io/restic", a.client) if err != nil { return nil, err } @@ -261,7 +261,7 @@ func getSecurityContext(log logrus.FieldLogger, config *corev1.ConfigMap) (strin // TODO eventually this can move to pkg/plugin/framework since it'll be used across multiple // plugins. -func getPluginConfig(kind framework.PluginKind, name string, client corev1client.ConfigMapInterface) (*corev1.ConfigMap, error) { +func getPluginConfig(kind common.PluginKind, name string, client corev1client.ConfigMapInterface) (*corev1.ConfigMap, error) { opts := metav1.ListOptions{ // velero.io/plugin-config: true // velero.io/restic: RestoreItemAction diff --git a/pkg/restore/restore.go b/pkg/restore/restore.go index a2794bdfc..37b0f6b01 100644 --- a/pkg/restore/restore.go +++ b/pkg/restore/restore.go @@ -226,12 +226,12 @@ func (kr *kubernetesRestorer) RestoreWithResolvers( Includes(req.Restore.Spec.IncludedNamespaces...). Excludes(req.Restore.Spec.ExcludedNamespaces...) - resolvedActions, err := restoreItemActionResolver.ResolveActions(kr.discoveryHelper) + resolvedActions, err := restoreItemActionResolver.ResolveActions(kr.discoveryHelper, kr.logger) if err != nil { return Result{}, Result{Velero: []string{err.Error()}} } - resolvedItemSnapshotterActions, err := itemSnapshotterResolver.ResolveActions(kr.discoveryHelper) + resolvedItemSnapshotterActions, err := itemSnapshotterResolver.ResolveActions(kr.discoveryHelper, kr.logger) if err != nil { return Result{}, Result{Velero: []string{err.Error()}} }