plugin/framework refactoring for BackupItemAction v1

Refactors the framework  package to implement the plugin versioning changes
needed for BIA v1 and overall package refactoring to support plugin versions
in different packages. This should be all that's needed to move on to
v2 for BackupItemAction. The remaining plugin types still need similar
refactoring to what's being done here for BIA before attempting a
v2 implementation.

Signed-off-by: Scott Seago <sseago@redhat.com>
This commit is contained in:
Scott Seago
2022-09-15 11:15:30 -04:00
parent 4262b47536
commit e3e2a8dfa0
65 changed files with 567 additions and 518 deletions
@@ -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...),
@@ -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...),
+2 -2
View File
@@ -23,7 +23,7 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
)
type ProcessFactory interface {
@@ -132,7 +132,7 @@ func (r *process) dispense(key KindAndName) (interface{}, error) {
}
// Currently all plugins except for PluginLister dispense clientDispenser instances.
if clientDispenser, ok := dispensed.(framework.ClientDispenser); ok {
if clientDispenser, ok := dispensed.(common.ClientDispenser); ok {
if key.Name == "" {
return nil, errors.Errorf("%s plugin requested but name is missing", key.Kind.String())
}
@@ -24,6 +24,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
)
type mockClientProtocol struct {
@@ -96,7 +97,7 @@ func TestDispense(t *testing.T) {
key := KindAndName{}
if tc.clientDispenser {
key.Kind = framework.PluginKindObjectStore
key.Kind = common.PluginKindObjectStore
protocolClient.On("Dispense", key.Kind.String()).Return(clientDispenser, tc.dispenseError)
if !tc.missingKeyName {
@@ -105,7 +106,7 @@ func TestDispense(t *testing.T) {
clientDispenser.On("ClientFor", key.Name).Return(client)
}
} else {
key.Kind = framework.PluginKindPluginLister
key.Kind = common.PluginKindPluginLister
client = &framework.PluginListerGRPCClient{}
protocolClient.On("Dispense", key.Kind.String()).Return(client, tc.dispenseError)
}
+21 -11
View File
@@ -25,6 +25,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/vmware-tanzu/velero/pkg/plugin/framework"
"github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
"github.com/vmware-tanzu/velero/pkg/util/filesystem"
)
@@ -33,14 +34,14 @@ type Registry interface {
// DiscoverPlugins discovers all available plugins.
DiscoverPlugins() error
// List returns all PluginIdentifiers for kind.
List(kind framework.PluginKind) []framework.PluginIdentifier
List(kind common.PluginKind) []framework.PluginIdentifier
// Get returns the PluginIdentifier for kind and name.
Get(kind framework.PluginKind, name string) (framework.PluginIdentifier, error)
Get(kind common.PluginKind, name string) (framework.PluginIdentifier, error)
}
// KindAndName is a convenience struct that combines a PluginKind and a name.
type KindAndName struct {
Kind framework.PluginKind
Kind common.PluginKind
Name string
}
@@ -54,7 +55,7 @@ type registry struct {
processFactory ProcessFactory
fs filesystem.Interface
pluginsByID map[KindAndName]framework.PluginIdentifier
pluginsByKind map[framework.PluginKind][]framework.PluginIdentifier
pluginsByKind map[common.PluginKind][]framework.PluginIdentifier
}
// NewRegistry returns a new registry.
@@ -67,7 +68,7 @@ func NewRegistry(dir string, logger logrus.FieldLogger, logLevel logrus.Level) R
processFactory: newProcessFactory(),
fs: filesystem.NewFileSystem(),
pluginsByID: make(map[KindAndName]framework.PluginIdentifier),
pluginsByKind: make(map[framework.PluginKind][]framework.PluginIdentifier),
pluginsByKind: make(map[common.PluginKind][]framework.PluginIdentifier),
}
}
@@ -110,13 +111,13 @@ func (r *registry) discoverPlugins(commands []string) error {
// List returns info about all plugin binaries that implement the given
// PluginKind.
func (r *registry) List(kind framework.PluginKind) []framework.PluginIdentifier {
func (r *registry) List(kind common.PluginKind) []framework.PluginIdentifier {
return r.pluginsByKind[kind]
}
// Get returns info about a plugin with the given name and kind, or an
// error if one cannot be found.
func (r *registry) Get(kind framework.PluginKind, name string) (framework.PluginIdentifier, error) {
func (r *registry) Get(kind common.PluginKind, name string) (framework.PluginIdentifier, error) {
p, found := r.pluginsByID[KindAndName{Kind: kind, Name: name}]
if !found {
return framework.PluginIdentifier{}, newPluginNotFoundError(kind, name)
@@ -182,7 +183,7 @@ func (r *registry) listPlugins(command string) ([]framework.PluginIdentifier, er
}
defer process.kill()
plugin, err := process.dispense(KindAndName{Kind: framework.PluginKindPluginLister})
plugin, err := process.dispense(KindAndName{Kind: common.PluginKindPluginLister})
if err != nil {
return nil, err
}
@@ -203,24 +204,33 @@ func (r *registry) register(id framework.PluginIdentifier) error {
}
// no need to pass list of existing plugins since the check if this exists was done above
if err := framework.ValidatePluginName(id.Name, nil); err != nil {
if err := common.ValidatePluginName(id.Name, nil); err != nil {
return errors.Errorf("invalid plugin name %q: %s", id.Name, err)
}
r.pluginsByID[key] = id
r.pluginsByKind[id.Kind] = append(r.pluginsByKind[id.Kind], id)
// if id.Kind is adaptable to newer plugin versions, list it under the other versions as well
// If BackupItemAction is adaptable to BackupItemActionV2, then it would be listed under both
// kinds
if kinds, ok := common.PluginKindsAdaptableTo[id.Kind]; ok {
for _, kind := range kinds {
r.pluginsByKind[kind] = append(r.pluginsByKind[kind], id)
}
}
return nil
}
// pluginNotFoundError indicates a plugin could not be located for kind and name.
type PluginNotFoundError struct {
kind framework.PluginKind
kind common.PluginKind
name string
}
// newPluginNotFoundError returns a new pluginNotFoundError for kind and name.
func newPluginNotFoundError(kind framework.PluginKind, name string) *PluginNotFoundError {
func newPluginNotFoundError(kind common.PluginKind, name string) *PluginNotFoundError {
return &PluginNotFoundError{
kind: kind,
name: name,