Merge pull request #5271 from sseago/plugin-versioning-impl
plugin/clientmgmt and framework refactoring for BackupItemAction v1pull/5313/head
commit
e42352b2e4
|
@ -0,0 +1 @@
|
|||
plugin/clientmgmt refactoring for BackupItemAction v1
|
|
@ -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 {
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
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 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
|
||||
}
|
||||
|
||||
func AdaptedBackupItemActions() []AdaptedBackupItemAction {
|
||||
return []AdaptedBackupItemAction{
|
||||
{
|
||||
Kind: common.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: common.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
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package clientmgmt
|
||||
package v1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -26,9 +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/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
mocks "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks/backupitemaction/v1"
|
||||
)
|
||||
|
||||
func TestRestartableGetBackupItemAction(t *testing.T) {
|
||||
|
@ -50,7 +51,7 @@ func TestRestartableGetBackupItemAction(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "happy path",
|
||||
plugin: new(mocks.ItemAction),
|
||||
plugin: new(mocks.BackupItemAction),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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: common.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)
|
||||
expected := new(mocks.ItemAction)
|
||||
key := kindAndName{kind: framework.PluginKindBackupItemAction, name: name}
|
||||
p.On("getByKindAndName", key).Return(expected, nil)
|
||||
p.On("ResetIfNeeded").Return(nil)
|
||||
expected := new(mocks.BackupItemAction)
|
||||
key := process.KindAndName{Kind: common.PluginKindBackupItemAction, Name: name}
|
||||
p.On("GetByKindAndName", key).Return(expected, nil)
|
||||
|
||||
a, err = r.getDelegate()
|
||||
assert.NoError(t, err)
|
||||
|
@ -122,15 +123,15 @@ func TestRestartableBackupItemActionDelegatedFunctions(t *testing.T) {
|
|||
|
||||
runRestartableDelegateTests(
|
||||
t,
|
||||
framework.PluginKindBackupItemAction,
|
||||
func(key kindAndName, p RestartableProcess) interface{} {
|
||||
return &restartableBackupItemAction{
|
||||
key: key,
|
||||
sharedPluginProcess: p,
|
||||
common.PluginKindBackupItemAction,
|
||||
func(key process.KindAndName, p process.RestartableProcess) interface{} {
|
||||
return &RestartableBackupItemAction{
|
||||
Key: key,
|
||||
SharedPluginProcess: p,
|
||||
}
|
||||
},
|
||||
func() mockable {
|
||||
return new(mocks.ItemAction)
|
||||
return new(mocks.BackupItemAction)
|
||||
},
|
||||
restartableDelegateTest{
|
||||
function: "AppliesTo",
|
|
@ -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/common"
|
||||
)
|
||||
|
||||
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 common.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)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -17,12 +17,16 @@ limitations under the License.
|
|||
package clientmgmt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
|
||||
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/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"
|
||||
|
@ -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.
|
||||
|
@ -64,29 +68,32 @@ type Manager interface {
|
|||
CleanupClients()
|
||||
}
|
||||
|
||||
// Used checking for adapted plugin versions
|
||||
var pluginNotFoundErrType = &process.PluginNotFoundError{}
|
||||
|
||||
// manager implements Manager.
|
||||
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 +101,7 @@ func (m *manager) CleanupClients() {
|
|||
m.lock.Lock()
|
||||
|
||||
for _, restartableProcess := range m.restartableProcesses {
|
||||
restartableProcess.stop()
|
||||
restartableProcess.Stop()
|
||||
}
|
||||
|
||||
m.lock.Unlock()
|
||||
|
@ -102,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) (RestartableProcess, error) {
|
||||
func (m *manager) getRestartableProcess(kind common.PluginKind, name string) (process.RestartableProcess, error) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
|
@ -127,7 +134,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
|
||||
}
|
||||
|
@ -141,12 +148,12 @@ 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
|
||||
}
|
||||
|
||||
r := newRestartableObjectStore(name, restartableProcess)
|
||||
r := NewRestartableObjectStore(name, restartableProcess)
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
@ -155,19 +162,19 @@ 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
|
||||
}
|
||||
|
||||
r := newRestartableVolumeSnapshotter(name, restartableProcess)
|
||||
r := NewRestartableVolumeSnapshotter(name, restartableProcess)
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// 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))
|
||||
|
||||
|
@ -189,18 +196,23 @@ 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.As(err, &pluginNotFoundErrType) {
|
||||
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.
|
||||
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))
|
||||
|
||||
|
@ -222,18 +234,18 @@ 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
|
||||
}
|
||||
|
||||
r := newRestartableRestoreItemAction(name, restartableProcess)
|
||||
r := NewRestartableRestoreItemAction(name, restartableProcess)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// 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))
|
||||
|
||||
|
@ -255,29 +267,29 @@ 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
|
||||
}
|
||||
|
||||
r := newRestartableDeleteItemAction(name, restartableProcess)
|
||||
r := NewRestartableDeleteItemAction(name, restartableProcess)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
r := newRestartableItemSnapshotter(name, restartableProcess)
|
||||
r := NewRestartableItemSnapshotter(name, restartableProcess)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
|
|
|
@ -26,7 +26,10 @@ 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/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/test"
|
||||
)
|
||||
|
||||
|
@ -39,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 {
|
||||
|
@ -72,11 +75,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 +88,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()
|
||||
}
|
||||
|
||||
|
@ -121,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)
|
||||
|
@ -135,7 +138,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 +146,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 +169,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
|
||||
}
|
||||
|
||||
|
@ -175,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 RestartableProcess) interface{} {
|
||||
func(name string, sharedPluginProcess process.RestartableProcess) interface{} {
|
||||
return &restartableObjectStore{
|
||||
key: kindAndName{kind: framework.PluginKindObjectStore, name: name},
|
||||
key: process.KindAndName{Kind: common.PluginKindObjectStore, Name: name},
|
||||
sharedPluginProcess: sharedPluginProcess,
|
||||
}
|
||||
},
|
||||
|
@ -192,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 RestartableProcess) interface{} {
|
||||
func(name string, sharedPluginProcess process.RestartableProcess) interface{} {
|
||||
return &restartableVolumeSnapshotter{
|
||||
key: kindAndName{kind: framework.PluginKindVolumeSnapshotter, name: name},
|
||||
key: process.KindAndName{Kind: common.PluginKindVolumeSnapshotter, Name: name},
|
||||
sharedPluginProcess: sharedPluginProcess,
|
||||
}
|
||||
},
|
||||
|
@ -209,15 +212,15 @@ 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 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: common.PluginKindBackupItemAction, Name: name},
|
||||
SharedPluginProcess: sharedPluginProcess,
|
||||
}
|
||||
},
|
||||
false,
|
||||
|
@ -226,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 RestartableProcess) interface{} {
|
||||
func(name string, sharedPluginProcess process.RestartableProcess) interface{} {
|
||||
return &restartableRestoreItemAction{
|
||||
key: kindAndName{kind: framework.PluginKindRestoreItemAction, name: name},
|
||||
key: process.KindAndName{Kind: common.PluginKindRestoreItemAction, Name: name},
|
||||
sharedPluginProcess: sharedPluginProcess,
|
||||
}
|
||||
},
|
||||
|
@ -243,10 +246,10 @@ 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 RestartableProcess) interface{},
|
||||
expectedResultFunc func(name string, sharedPluginProcess process.RestartableProcess) interface{},
|
||||
reinitializable bool,
|
||||
) {
|
||||
logger := test.NewLogger()
|
||||
|
@ -273,18 +276,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 +309,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",
|
||||
|
@ -327,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{
|
||||
|
@ -349,20 +352,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 +374,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 +401,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",
|
||||
|
@ -419,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{
|
||||
|
@ -442,19 +445,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 +466,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{}
|
||||
|
@ -478,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 RestartableProcess) interface{} {
|
||||
func(name string, sharedPluginProcess process.RestartableProcess) interface{} {
|
||||
return &restartableDeleteItemAction{
|
||||
key: kindAndName{kind: framework.PluginKindDeleteItemAction, name: name},
|
||||
key: process.KindAndName{Kind: common.PluginKindDeleteItemAction, Name: name},
|
||||
sharedPluginProcess: sharedPluginProcess,
|
||||
}
|
||||
},
|
||||
|
@ -518,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{
|
||||
|
@ -541,19 +544,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 +565,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{}
|
||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
// Package clientmgmt contains the plugin client for Velero.
|
||||
package clientmgmt
|
||||
package process
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
@ -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...),
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package clientmgmt
|
||||
package process
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
@ -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...),
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package clientmgmt
|
||||
package process
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -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"
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package clientmgmt
|
||||
package process
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
@ -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 {
|
||||
|
@ -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 clientDispenser, ok := dispensed.(common.ClientDispenser); ok {
|
||||
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
|
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -94,20 +95,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 = common.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 = common.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)
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package clientmgmt
|
||||
package process
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -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,15 +34,15 @@ 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
|
||||
name string
|
||||
// KindAndName is a convenience struct that combines a PluginKind and a name.
|
||||
type KindAndName struct {
|
||||
Kind common.PluginKind
|
||||
Name string
|
||||
}
|
||||
|
||||
// registry implements Registry.
|
||||
|
@ -53,8 +54,8 @@ type registry struct {
|
|||
|
||||
processFactory ProcessFactory
|
||||
fs filesystem.Interface
|
||||
pluginsByID map[kindAndName]framework.PluginIdentifier
|
||||
pluginsByKind map[framework.PluginKind][]framework.PluginIdentifier
|
||||
pluginsByID map[KindAndName]framework.PluginIdentifier
|
||||
pluginsByKind map[common.PluginKind][]framework.PluginIdentifier
|
||||
}
|
||||
|
||||
// NewRegistry returns a new registry.
|
||||
|
@ -66,8 +67,8 @@ 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),
|
||||
pluginsByID: make(map[KindAndName]framework.PluginIdentifier),
|
||||
pluginsByKind: make(map[common.PluginKind][]framework.PluginIdentifier),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,14 +111,14 @@ 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) {
|
||||
p, found := r.pluginsByID[kindAndName{kind: kind, name: name}]
|
||||
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
|
||||
}
|
||||
|
@ -197,37 +198,46 @@ 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)
|
||||
}
|
||||
|
||||
// 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
|
||||
type PluginNotFoundError struct {
|
||||
kind common.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 common.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)
|
||||
}
|
||||
|
|
@ -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"
|
|
@ -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()
|
|
@ -24,7 +24,8 @@ import (
|
|||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
)
|
||||
|
||||
type restartableDelegateTest struct {
|
||||
|
@ -42,8 +43,8 @@ type mockable interface {
|
|||
|
||||
func runRestartableDelegateTests(
|
||||
t *testing.T,
|
||||
kind framework.PluginKind,
|
||||
newRestartable func(key kindAndName, p RestartableProcess) interface{},
|
||||
kind common.PluginKind,
|
||||
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...)
|
||||
|
|
|
@ -19,7 +19,8 @@ package clientmgmt
|
|||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
|
@ -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: common.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
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ 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"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
"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: common.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: common.PluginKindDeleteItemAction, Name: name}
|
||||
p.On("GetByKindAndName", key).Return(expected, nil)
|
||||
|
||||
a, err = r.getDelegate()
|
||||
assert.NoError(t, err)
|
||||
|
@ -115,8 +116,8 @@ func TestRestartableDeleteItemActionDelegatedFunctions(t *testing.T) {
|
|||
|
||||
runRestartableDelegateTests(
|
||||
t,
|
||||
framework.PluginKindDeleteItemAction,
|
||||
func(key kindAndName, p RestartableProcess) interface{} {
|
||||
common.PluginKindDeleteItemAction,
|
||||
func(key process.KindAndName, p process.RestartableProcess) interface{} {
|
||||
return &restartableDeleteItemAction{
|
||||
key: key,
|
||||
sharedPluginProcess: p,
|
||||
|
|
|
@ -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/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
|
||||
)
|
||||
|
||||
type restartableItemSnapshotter struct {
|
||||
key 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: common.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
|
||||
}
|
||||
|
||||
|
|
|
@ -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/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
isv1 "github.com/vmware-tanzu/velero/pkg/plugin/velero/item_snapshotter/v1"
|
||||
)
|
||||
|
||||
func TestRestartableGetItemSnapshotter(t *testing.T) {
|
||||
|
@ -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: common.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: common.PluginKindItemSnapshotter, Name: name}
|
||||
p.On("GetByKindAndName", key).Return(expected, nil)
|
||||
|
||||
a, err = r.getDelegate()
|
||||
assert.NoError(t, err)
|
||||
|
@ -177,8 +177,8 @@ func TestRestartableItemSnasphotterDelegatedFunctions(t *testing.T) {
|
|||
}
|
||||
runRestartableDelegateTests(
|
||||
t,
|
||||
framework.PluginKindItemSnapshotter,
|
||||
func(key kindAndName, p RestartableProcess) interface{} {
|
||||
common.PluginKindItemSnapshotter,
|
||||
func(key process.KindAndName, p process.RestartableProcess) interface{} {
|
||||
return &restartableItemSnapshotter{
|
||||
key: key,
|
||||
sharedPluginProcess: p,
|
||||
|
|
|
@ -22,7 +22,8 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
|
@ -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: common.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
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
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: common.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: common.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: common.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: common.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)
|
||||
|
@ -186,8 +187,8 @@ func TestRestartableObjectStoreInit(t *testing.T) {
|
|||
func TestRestartableObjectStoreDelegatedFunctions(t *testing.T) {
|
||||
runRestartableDelegateTests(
|
||||
t,
|
||||
framework.PluginKindObjectStore,
|
||||
func(key kindAndName, p RestartableProcess) interface{} {
|
||||
common.PluginKindObjectStore,
|
||||
func(key process.KindAndName, p process.RestartableProcess) interface{} {
|
||||
return &restartableObjectStore{
|
||||
key: key,
|
||||
sharedPluginProcess: p,
|
||||
|
|
|
@ -19,24 +19,25 @@ package clientmgmt
|
|||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// 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: common.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
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ 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/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
"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: common.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: common.PluginKindRestoreItemAction, Name: name}
|
||||
p.On("GetByKindAndName", key).Return(expected, nil)
|
||||
|
||||
a, err = r.getDelegate()
|
||||
assert.NoError(t, err)
|
||||
|
@ -121,8 +122,8 @@ func TestRestartableRestoreItemActionDelegatedFunctions(t *testing.T) {
|
|||
|
||||
runRestartableDelegateTests(
|
||||
t,
|
||||
framework.PluginKindRestoreItemAction,
|
||||
func(key kindAndName, p RestartableProcess) interface{} {
|
||||
common.PluginKindRestoreItemAction,
|
||||
func(key process.KindAndName, p process.RestartableProcess) interface{} {
|
||||
return &restartableRestoreItemAction{
|
||||
key: key,
|
||||
sharedPluginProcess: p,
|
||||
|
|
|
@ -20,36 +20,37 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// 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: common.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
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt/process"
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
|
||||
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: common.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: common.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: common.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: common.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)
|
||||
|
@ -197,8 +198,8 @@ func TestRestartableVolumeSnapshotterDelegatedFunctions(t *testing.T) {
|
|||
|
||||
runRestartableDelegateTests(
|
||||
t,
|
||||
framework.PluginKindVolumeSnapshotter,
|
||||
func(key kindAndName, p RestartableProcess) interface{} {
|
||||
common.PluginKindVolumeSnapshotter,
|
||||
func(key process.KindAndName, p process.RestartableProcess) interface{} {
|
||||
return &restartableVolumeSnapshotter{
|
||||
key: key,
|
||||
sharedPluginProcess: p,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}}
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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 ""
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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 {
|
|
@ -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
|
||||
}
|
|
@ -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:
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package framework
|
||||
package common
|
||||
|
||||
import (
|
||||
"strings"
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <DNS subdomain>/<non-empty name>.
|
||||
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 <DNS subdomain>/<non-empty name>.
|
||||
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 <DNS subdomain>/<non-empty name>.
|
||||
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 <DNS subdomain>/<non-empty name>.
|
||||
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 <DNS subdomain>/<non-empty name>.
|
||||
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,
|
||||
})
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue