diff --git a/changelogs/unreleased/2808-nrb b/changelogs/unreleased/2808-nrb new file mode 100644 index 000000000..89ba87d28 --- /dev/null +++ b/changelogs/unreleased/2808-nrb @@ -0,0 +1 @@ +Add the DeleteItemAction plugin type diff --git a/pkg/plugin/clientmgmt/manager.go b/pkg/plugin/clientmgmt/manager.go index 32c0884bf..18705bae4 100644 --- a/pkg/plugin/clientmgmt/manager.go +++ b/pkg/plugin/clientmgmt/manager.go @@ -1,5 +1,5 @@ /* -Copyright 2017 the Velero contributors. +Copyright 2020 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. @@ -46,6 +46,12 @@ type Manager interface { // GetRestoreItemAction returns the restore item action plugin for name. GetRestoreItemAction(name string) (velero.RestoreItemAction, error) + // GetDeleteItemActions returns all delete item action plugins. + GetDeleteItemActions() ([]velero.DeleteItemAction, error) + + // GetDeleteItemAction returns the delete item action plugin for name. + GetDeleteItemAction(name string) (velero.DeleteItemAction, error) + // CleanupClients terminates all of the Manager's running plugin processes. CleanupClients() } @@ -224,3 +230,39 @@ func (m *manager) GetRestoreItemAction(name string) (velero.RestoreItemAction, e 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) + + actions := make([]velero.DeleteItemAction, 0, len(list)) + + for i := range list { + id := list[i] + + r, err := m.GetDeleteItemAction(id.Name) + if err != nil { + return nil, err + } + + actions = append(actions, r) + } + + return actions, nil +} + +// GetDeleteItemAction returns a restartableDeleteItemAction for name. +func (m *manager) GetDeleteItemAction(name string) (velero.DeleteItemAction, error) { + // Backwards compatibility with non-namespaced plugins, following principle of least surprise + // since DeleteItemActions were not bundled with Velero when plugins were non-namespaced. + if !strings.Contains(name, "/") { + name = "velero.io/" + name + } + restartableProcess, err := m.getRestartableProcess(framework.PluginKindDeleteItemAction, name) + if err != nil { + return nil, err + } + + r := newRestartableDeleteItemAction(name, restartableProcess) + return r, nil +} diff --git a/pkg/plugin/clientmgmt/manager_test.go b/pkg/plugin/clientmgmt/manager_test.go index 3688b8a3f..4be23b25a 100644 --- a/pkg/plugin/clientmgmt/manager_test.go +++ b/pkg/plugin/clientmgmt/manager_test.go @@ -1,5 +1,5 @@ /* -Copyright 2018 the Velero contributors. +Copyright 2020 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. @@ -475,3 +475,102 @@ func TestGetRestoreItemActions(t *testing.T) { }) } } + +func TestGetDeleteItemAction(t *testing.T) { + getPluginTest(t, + framework.PluginKindDeleteItemAction, + "velero.io/deleter", + func(m Manager, name string) (interface{}, error) { + return m.GetDeleteItemAction(name) + }, + func(name string, sharedPluginProcess RestartableProcess) interface{} { + return &restartableDeleteItemAction{ + key: kindAndName{kind: framework.PluginKindDeleteItemAction, name: name}, + sharedPluginProcess: sharedPluginProcess, + } + }, + false, + ) +} + +func TestGetDeleteItemActions(t *testing.T) { + tests := []struct { + name string + names []string + newRestartableProcessError error + expectedError string + }{ + { + name: "No items", + names: []string{}, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + logger := test.NewLogger() + logLevel := logrus.InfoLevel + + registry := &mockRegistry{} + defer registry.AssertExpectations(t) + + m := NewManager(logger, logLevel, registry).(*manager) + factory := &mockRestartableProcessFactory{} + defer factory.AssertExpectations(t) + m.restartableProcessFactory = factory + + pluginKind := framework.PluginKindDeleteItemAction + var pluginIDs []framework.PluginIdentifier + for i := range tc.names { + pluginID := framework.PluginIdentifier{ + Command: "/command", + Kind: pluginKind, + Name: tc.names[i], + } + pluginIDs = append(pluginIDs, pluginID) + } + registry.On("List", pluginKind).Return(pluginIDs) + + var expectedActions []interface{} + for i := range pluginIDs { + pluginID := pluginIDs[i] + pluginName := pluginID.Name + + registry.On("Get", pluginKind, pluginName).Return(pluginID, nil) + + restartableProcess := &mockRestartableProcess{} + defer restartableProcess.AssertExpectations(t) + + expected := &restartableRestoreItemAction{ + key: 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() + break + } + + // Test 2: happy path + if i == 0 { + factory.On("newRestartableProcess", pluginID.Command, logger, logLevel).Return(restartableProcess, nil).Once() + } + + expectedActions = append(expectedActions, expected) + } + + deleteItemActions, err := m.GetDeleteItemActions() + if tc.newRestartableProcessError != nil { + assert.Nil(t, deleteItemActions) + assert.EqualError(t, err, "newRestartableProcess") + } else { + require.NoError(t, err) + var actual []interface{} + for i := range deleteItemActions { + actual = append(actual, deleteItemActions[i]) + } + assert.Equal(t, expectedActions, actual) + } + }) + } +} diff --git a/pkg/plugin/clientmgmt/restartable_delete_item_action.go b/pkg/plugin/clientmgmt/restartable_delete_item_action.go new file mode 100644 index 000000000..266500c7a --- /dev/null +++ b/pkg/plugin/clientmgmt/restartable_delete_item_action.go @@ -0,0 +1,88 @@ +/* +Copyright 2020 the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package clientmgmt + +import ( + "github.com/pkg/errors" + + "github.com/vmware-tanzu/velero/pkg/plugin/framework" + "github.com/vmware-tanzu/velero/pkg/plugin/velero" +) + +// restartableDeleteItemAction is a delete 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 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 + config map[string]string +} + +// newRestartableDeleteItemAction returns a new restartableDeleteItemAction. +func newRestartableDeleteItemAction(name string, sharedPluginProcess RestartableProcess) *restartableDeleteItemAction { + r := &restartableDeleteItemAction{ + key: kindAndName{kind: framework.PluginKindDeleteItemAction, name: name}, + sharedPluginProcess: sharedPluginProcess, + } + return r +} + +// 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) + if err != nil { + return nil, err + } + + deleteItemAction, ok := plugin.(velero.DeleteItemAction) + if !ok { + return nil, errors.Errorf("%T is not a DeleteItemAction!", plugin) + } + + return deleteItemAction, nil +} + +// 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 { + return nil, err + } + + return r.getDeleteItemAction() +} + +// AppliesTo restarts the plugin's process if needed, then delegates the call. +func (r *restartableDeleteItemAction) AppliesTo() (velero.ResourceSelector, error) { + delegate, err := r.getDelegate() + if err != nil { + return velero.ResourceSelector{}, err + } + + return delegate.AppliesTo() +} + +// Execute restarts the plugin's process if needed, then delegates the call. +func (r *restartableDeleteItemAction) Execute(input *velero.DeleteItemActionExecuteInput) error { + delegate, err := r.getDelegate() + if err != nil { + return err + } + + return delegate.Execute(input) +} diff --git a/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go b/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go new file mode 100644 index 000000000..641959e17 --- /dev/null +++ b/pkg/plugin/clientmgmt/restartable_delete_item_action_test.go @@ -0,0 +1,142 @@ +/* +Copyright 2020 the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package clientmgmt + +import ( + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "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/velero" + "github.com/vmware-tanzu/velero/pkg/plugin/velero/mocks" +) + +func TestRestartableGetDeleteItemAction(t *testing.T) { + tests := []struct { + name string + plugin interface{} + getError error + expectedError string + }{ + { + name: "error getting by kind and name", + getError: errors.Errorf("get error"), + expectedError: "get error", + }, + { + name: "wrong type", + plugin: 3, + expectedError: "int is not a DeleteItemAction!", + }, + { + name: "happy path", + plugin: new(mocks.DeleteItemAction), + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + p := new(mockRestartableProcess) + defer p.AssertExpectations(t) + + name := "pod" + key := kindAndName{kind: framework.PluginKindDeleteItemAction, name: name} + p.On("getByKindAndName", key).Return(tc.plugin, tc.getError) + + r := newRestartableDeleteItemAction(name, p) + a, err := r.getDeleteItemAction() + if tc.expectedError != "" { + assert.EqualError(t, err, tc.expectedError) + return + } + require.NoError(t, err) + + assert.Equal(t, tc.plugin, a) + }) + } +} + +func TestRestartableDeleteItemActionGetDelegate(t *testing.T) { + p := new(mockRestartableProcess) + defer p.AssertExpectations(t) + + // Reset error + p.On("resetIfNeeded").Return(errors.Errorf("reset error")).Once() + name := "pod" + 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) + expected := new(mocks.DeleteItemAction) + key := kindAndName{kind: framework.PluginKindDeleteItemAction, name: name} + p.On("getByKindAndName", key).Return(expected, nil) + + a, err = r.getDelegate() + assert.NoError(t, err) + assert.Equal(t, expected, a) +} + +func TestRestartableDeleteItemActionDelegatedFunctions(t *testing.T) { + pv := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "color": "blue", + }, + } + + backup := &api.Backup{} + + input := &velero.DeleteItemActionExecuteInput{ + Item: pv, + Backup: backup, + } + + runRestartableDelegateTests( + t, + framework.PluginKindDeleteItemAction, + func(key kindAndName, p RestartableProcess) interface{} { + return &restartableDeleteItemAction{ + key: key, + sharedPluginProcess: p, + } + }, + func() mockable { + // Currently broken because this mocks the restore item action interface + return new(mocks.DeleteItemAction) + }, + restartableDelegateTest{ + function: "AppliesTo", + inputs: []interface{}{}, + expectedErrorOutputs: []interface{}{velero.ResourceSelector{}, errors.Errorf("reset error")}, + expectedDelegateOutputs: []interface{}{velero.ResourceSelector{IncludedNamespaces: []string{"a"}}, errors.Errorf("delegate error")}, + }, + restartableDelegateTest{ + function: "Execute", + inputs: []interface{}{input}, + expectedErrorOutputs: []interface{}{errors.Errorf("reset error")}, + expectedDelegateOutputs: []interface{}{errors.Errorf("delegate error")}, + }, + ) +} diff --git a/pkg/plugin/framework/delete_item_action.go b/pkg/plugin/framework/delete_item_action.go new file mode 100644 index 000000000..fc9be502c --- /dev/null +++ b/pkg/plugin/framework/delete_item_action.go @@ -0,0 +1,44 @@ +/* +Copyright 2020 the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package framework + +import ( + plugin "github.com/hashicorp/go-plugin" + "golang.org/x/net/context" + "google.golang.org/grpc" + + proto "github.com/vmware-tanzu/velero/pkg/plugin/generated" +) + +// RestoreItemActionPlugin is an implementation of go-plugin's Plugin +// interface with support for gRPC for the restore/ItemAction +// interface. +type DeleteItemActionPlugin struct { + plugin.NetRPCUnsupportedPlugin + *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 +} + +// GRPCServer registers a DeleteItemAction gRPC server. +func (p *DeleteItemActionPlugin) GRPCServer(_ *plugin.GRPCBroker, server *grpc.Server) error { + proto.RegisterDeleteItemActionServer(server, &DeleteItemActionGRPCServer{mux: p.serverMux}) + return nil +} diff --git a/pkg/plugin/framework/delete_item_action_client.go b/pkg/plugin/framework/delete_item_action_client.go new file mode 100644 index 000000000..e9adae6d0 --- /dev/null +++ b/pkg/plugin/framework/delete_item_action_client.go @@ -0,0 +1,95 @@ +/* +Copyright 2020 the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package framework + +import ( + "encoding/json" + + "github.com/pkg/errors" + "golang.org/x/net/context" + "google.golang.org/grpc" + + proto "github.com/vmware-tanzu/velero/pkg/plugin/generated" + "github.com/vmware-tanzu/velero/pkg/plugin/velero" +) + +var _ velero.DeleteItemAction = &DeleteItemActionGRPCClient{} + +// NewDeleteItemActionPlugin constructs a DeleteItemActionPlugin. +func NewDeleteItemActionPlugin(options ...PluginOption) *DeleteItemActionPlugin { + return &DeleteItemActionPlugin{ + pluginBase: newPluginBase(options...), + } +} + +// DeleteItemActionGRPCClient implements the backup/ItemAction interface and uses a +// gRPC client to make calls to the plugin server. +type DeleteItemActionGRPCClient struct { + *clientBase + grpcClient proto.DeleteItemActionClient +} + +func newDeleteItemActionGRPCClient(base *clientBase, clientConn *grpc.ClientConn) interface{} { + return &DeleteItemActionGRPCClient{ + 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}) + if err != nil { + return velero.ResourceSelector{}, fromGRPCError(err) + } + + if res.ResourceSelector == nil { + return velero.ResourceSelector{}, nil + } + + return velero.ResourceSelector{ + IncludedNamespaces: res.ResourceSelector.IncludedNamespaces, + ExcludedNamespaces: res.ResourceSelector.ExcludedNamespaces, + IncludedResources: res.ResourceSelector.IncludedResources, + ExcludedResources: res.ResourceSelector.ExcludedResources, + LabelSelector: res.ResourceSelector.Selector, + }, nil +} + +func (c *DeleteItemActionGRPCClient) Execute(input *velero.DeleteItemActionExecuteInput) error { + itemJSON, err := json.Marshal(input.Item.UnstructuredContent()) + if err != nil { + return errors.WithStack(err) + } + + backupJSON, err := json.Marshal(input.Backup) + if err != nil { + return errors.WithStack(err) + } + + req := &proto.DeleteItemActionExecuteRequest{ + 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 nil +} diff --git a/pkg/plugin/framework/delete_item_action_server.go b/pkg/plugin/framework/delete_item_action_server.go new file mode 100644 index 000000000..4bdaa06ae --- /dev/null +++ b/pkg/plugin/framework/delete_item_action_server.go @@ -0,0 +1,112 @@ +/* +Copyright 2020 the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package framework + +import ( + "encoding/json" + + "github.com/pkg/errors" + "golang.org/x/net/context" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + proto "github.com/vmware-tanzu/velero/pkg/plugin/generated" + "github.com/vmware-tanzu/velero/pkg/plugin/velero" +) + +// 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 +} + +func (s *DeleteItemActionGRPCServer) getImpl(name string) (velero.DeleteItemAction, error) { + impl, err := s.mux.getHandler(name) + if err != nil { + return nil, err + } + + itemAction, ok := impl.(velero.DeleteItemAction) + if !ok { + return nil, errors.Errorf("%T is not a delete item action", impl) + } + + return itemAction, nil +} + +func (s *DeleteItemActionGRPCServer) AppliesTo(ctx context.Context, req *proto.DeleteItemActionAppliesToRequest) (response *proto.DeleteItemActionAppliesToResponse, err error) { + defer func() { + if recoveredErr := handlePanic(recover()); recoveredErr != nil { + err = recoveredErr + } + }() + + impl, err := s.getImpl(req.Plugin) + if err != nil { + return nil, newGRPCError(err) + } + + resourceSelector, err := impl.AppliesTo() + if err != nil { + return nil, newGRPCError(err) + } + + return &proto.DeleteItemActionAppliesToResponse{ + &proto.ResourceSelector{ + IncludedNamespaces: resourceSelector.IncludedNamespaces, + ExcludedNamespaces: resourceSelector.ExcludedNamespaces, + IncludedResources: resourceSelector.IncludedResources, + ExcludedResources: resourceSelector.ExcludedResources, + Selector: resourceSelector.LabelSelector, + }, + }, nil +} + +func (s *DeleteItemActionGRPCServer) Execute(ctx context.Context, req *proto.DeleteItemActionExecuteRequest) (_ *proto.Empty, err error) { + defer func() { + if recoveredErr := handlePanic(recover()); recoveredErr != nil { + err = recoveredErr + } + }() + + impl, err := s.getImpl(req.Plugin) + if err != nil { + return nil, newGRPCError(err) + } + + var ( + item unstructured.Unstructured + backup api.Backup + ) + + if err := json.Unmarshal(req.Item, &item); err != nil { + return nil, newGRPCError(errors.WithStack(err)) + } + + if err = json.Unmarshal(req.Backup, &backup); err != nil { + return nil, newGRPCError(errors.WithStack(err)) + } + + if err := impl.Execute(&velero.DeleteItemActionExecuteInput{ + Item: &item, + Backup: &backup, + }); err != nil { + return nil, newGRPCError(err) + } + + return nil, nil +} diff --git a/pkg/plugin/framework/examples_test.go b/pkg/plugin/framework/examples_test.go index eae9eaccc..16ce5bd49 100644 --- a/pkg/plugin/framework/examples_test.go +++ b/pkg/plugin/framework/examples_test.go @@ -1,5 +1,5 @@ /* -Copyright 2019 the Velero contributors. +Copyright 2020 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. @@ -19,12 +19,15 @@ package framework import ( "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/runtime" + + "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) func ExampleNewServer_volumeSnapshotter() { NewServer(). // call the server RegisterVolumeSnapshotter("example.io/volumesnapshotter", newVolumeSnapshotter). // register the plugin with a valid name - Serve() // serve the plugin + RegisterDeleteItemAction("example.io/delete-item-action", newDeleteItemAction). + Serve() // serve the plugin } func newVolumeSnapshotter(logger logrus.FieldLogger) (interface{}, error) { @@ -91,3 +94,29 @@ func (b *VolumeSnapshotter) DeleteSnapshot(snapshotID string) error { return nil } + +// Implement all methods for the DeleteItemAction interface + +func newDeleteItemAction(logger logrus.FieldLogger) (interface{}, error) { + return DeleteItemAction{FieldLogger: logger}, nil +} + +type DeleteItemAction struct { + FieldLogger logrus.FieldLogger +} + +func (d *DeleteItemAction) AppliesTo() (velero.ResourceSelector, error) { + d.FieldLogger.Infof("AppliesTo called") + + // ... + + return velero.ResourceSelector{}, nil +} + +func (d *DeleteItemAction) Execute(input *velero.DeleteItemActionExecuteInput) error { + d.FieldLogger.Infof("Execute called") + + // ... + + return nil +} diff --git a/pkg/plugin/framework/plugin_kinds.go b/pkg/plugin/framework/plugin_kinds.go index f80685c1b..640ae30b8 100644 --- a/pkg/plugin/framework/plugin_kinds.go +++ b/pkg/plugin/framework/plugin_kinds.go @@ -38,6 +38,9 @@ const ( // PluginKindRestoreItemAction represents a restore item action plugin. PluginKindRestoreItemAction PluginKind = "RestoreItemAction" + // PluginKindDeleteItemAction represents a delete item action plugin. + PluginKindDeleteItemAction PluginKind = "DeleteItemAction" + // PluginKindPluginLister represents a plugin lister plugin. PluginKindPluginLister PluginKind = "PluginLister" ) @@ -50,5 +53,6 @@ func AllPluginKinds() map[string]PluginKind { allPluginKinds[PluginKindVolumeSnapshotter.String()] = PluginKindVolumeSnapshotter allPluginKinds[PluginKindBackupItemAction.String()] = PluginKindBackupItemAction allPluginKinds[PluginKindRestoreItemAction.String()] = PluginKindRestoreItemAction + allPluginKinds[PluginKindDeleteItemAction.String()] = PluginKindDeleteItemAction return allPluginKinds } diff --git a/pkg/plugin/framework/server.go b/pkg/plugin/framework/server.go index 844315eb0..20893f921 100644 --- a/pkg/plugin/framework/server.go +++ b/pkg/plugin/framework/server.go @@ -67,6 +67,13 @@ type Server interface { // RegisterRestoreItemActions registers multiple restore item actions. RegisterRestoreItemActions(map[string]HandlerInitializer) Server + // RegisterDeleteItemAction registers a delete item action. Accepted format + // for the plugin name is /. + RegisterDeleteItemAction(pluginName string, initializer HandlerInitializer) Server + + // RegisterDeleteItemActions registers multiple Delete item actions. + RegisterDeleteItemActions(map[string]HandlerInitializer) Server + // Server runs the plugin server. Serve() } @@ -81,6 +88,7 @@ type server struct { volumeSnapshotter *VolumeSnapshotterPlugin objectStore *ObjectStorePlugin restoreItemAction *RestoreItemActionPlugin + deleteItemAction *DeleteItemActionPlugin } // NewServer returns a new Server @@ -96,6 +104,7 @@ func NewServer() Server { volumeSnapshotter: NewVolumeSnapshotterPlugin(serverLogger(log)), objectStore: NewObjectStorePlugin(serverLogger(log)), restoreItemAction: NewRestoreItemActionPlugin(serverLogger(log)), + deleteItemAction: NewDeleteItemActionPlugin(serverLogger(log)), } } @@ -156,6 +165,18 @@ func (s *server) RegisterRestoreItemActions(m map[string]HandlerInitializer) Ser return s } +func (s *server) RegisterDeleteItemAction(name string, initializer HandlerInitializer) Server { + s.deleteItemAction.register(name, initializer) + return s +} + +func (s *server) RegisterDeleteItemActions(m map[string]HandlerInitializer) Server { + for name := range m { + s.RegisterDeleteItemAction(name, m[name]) + } + return s +} + // getNames returns a list of PluginIdentifiers registered with plugin. func getNames(command string, kind PluginKind, plugin Interface) []PluginIdentifier { var pluginIdentifiers []PluginIdentifier diff --git a/pkg/plugin/generated/BackupItemAction.pb.go b/pkg/plugin/generated/BackupItemAction.pb.go index e8f15519c..9e3afd9fc 100644 --- a/pkg/plugin/generated/BackupItemAction.pb.go +++ b/pkg/plugin/generated/BackupItemAction.pb.go @@ -6,6 +6,7 @@ Package generated is a generated protocol buffer package. It is generated from these files: BackupItemAction.proto + DeleteItemAction.proto ObjectStore.proto PluginLister.proto RestoreItemAction.proto @@ -17,6 +18,9 @@ It has these top-level messages: ExecuteResponse BackupItemActionAppliesToRequest BackupItemActionAppliesToResponse + DeleteItemActionExecuteRequest + DeleteItemActionAppliesToRequest + DeleteItemActionAppliesToResponse PutObjectRequest ObjectExistsRequest ObjectExistsResponse diff --git a/pkg/plugin/generated/DeleteItemAction.pb.go b/pkg/plugin/generated/DeleteItemAction.pb.go new file mode 100644 index 000000000..1d0f64680 --- /dev/null +++ b/pkg/plugin/generated/DeleteItemAction.pb.go @@ -0,0 +1,219 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: DeleteItemAction.proto + +package generated + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type DeleteItemActionExecuteRequest struct { + Plugin string `protobuf:"bytes,1,opt,name=plugin" json:"plugin,omitempty"` + Item []byte `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"` + Backup []byte `protobuf:"bytes,3,opt,name=backup,proto3" json:"backup,omitempty"` +} + +func (m *DeleteItemActionExecuteRequest) Reset() { *m = DeleteItemActionExecuteRequest{} } +func (m *DeleteItemActionExecuteRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteItemActionExecuteRequest) ProtoMessage() {} +func (*DeleteItemActionExecuteRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +func (m *DeleteItemActionExecuteRequest) GetPlugin() string { + if m != nil { + return m.Plugin + } + return "" +} + +func (m *DeleteItemActionExecuteRequest) GetItem() []byte { + if m != nil { + return m.Item + } + return nil +} + +func (m *DeleteItemActionExecuteRequest) GetBackup() []byte { + if m != nil { + return m.Backup + } + return nil +} + +type DeleteItemActionAppliesToRequest struct { + Plugin string `protobuf:"bytes,1,opt,name=plugin" json:"plugin,omitempty"` +} + +func (m *DeleteItemActionAppliesToRequest) Reset() { *m = DeleteItemActionAppliesToRequest{} } +func (m *DeleteItemActionAppliesToRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteItemActionAppliesToRequest) ProtoMessage() {} +func (*DeleteItemActionAppliesToRequest) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{1} +} + +func (m *DeleteItemActionAppliesToRequest) GetPlugin() string { + if m != nil { + return m.Plugin + } + return "" +} + +type DeleteItemActionAppliesToResponse struct { + ResourceSelector *ResourceSelector `protobuf:"bytes,1,opt,name=ResourceSelector" json:"ResourceSelector,omitempty"` +} + +func (m *DeleteItemActionAppliesToResponse) Reset() { *m = DeleteItemActionAppliesToResponse{} } +func (m *DeleteItemActionAppliesToResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteItemActionAppliesToResponse) ProtoMessage() {} +func (*DeleteItemActionAppliesToResponse) Descriptor() ([]byte, []int) { + return fileDescriptor1, []int{2} +} + +func (m *DeleteItemActionAppliesToResponse) GetResourceSelector() *ResourceSelector { + if m != nil { + return m.ResourceSelector + } + return nil +} + +func init() { + proto.RegisterType((*DeleteItemActionExecuteRequest)(nil), "generated.DeleteItemActionExecuteRequest") + proto.RegisterType((*DeleteItemActionAppliesToRequest)(nil), "generated.DeleteItemActionAppliesToRequest") + proto.RegisterType((*DeleteItemActionAppliesToResponse)(nil), "generated.DeleteItemActionAppliesToResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for DeleteItemAction service + +type DeleteItemActionClient interface { + AppliesTo(ctx context.Context, in *DeleteItemActionAppliesToRequest, opts ...grpc.CallOption) (*DeleteItemActionAppliesToResponse, error) + Execute(ctx context.Context, in *DeleteItemActionExecuteRequest, opts ...grpc.CallOption) (*Empty, error) +} + +type deleteItemActionClient struct { + cc *grpc.ClientConn +} + +func NewDeleteItemActionClient(cc *grpc.ClientConn) DeleteItemActionClient { + return &deleteItemActionClient{cc} +} + +func (c *deleteItemActionClient) AppliesTo(ctx context.Context, in *DeleteItemActionAppliesToRequest, opts ...grpc.CallOption) (*DeleteItemActionAppliesToResponse, error) { + out := new(DeleteItemActionAppliesToResponse) + err := grpc.Invoke(ctx, "/generated.DeleteItemAction/AppliesTo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *deleteItemActionClient) Execute(ctx context.Context, in *DeleteItemActionExecuteRequest, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := grpc.Invoke(ctx, "/generated.DeleteItemAction/Execute", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for DeleteItemAction service + +type DeleteItemActionServer interface { + AppliesTo(context.Context, *DeleteItemActionAppliesToRequest) (*DeleteItemActionAppliesToResponse, error) + Execute(context.Context, *DeleteItemActionExecuteRequest) (*Empty, error) +} + +func RegisterDeleteItemActionServer(s *grpc.Server, srv DeleteItemActionServer) { + s.RegisterService(&_DeleteItemAction_serviceDesc, srv) +} + +func _DeleteItemAction_AppliesTo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteItemActionAppliesToRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DeleteItemActionServer).AppliesTo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/generated.DeleteItemAction/AppliesTo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DeleteItemActionServer).AppliesTo(ctx, req.(*DeleteItemActionAppliesToRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DeleteItemAction_Execute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteItemActionExecuteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DeleteItemActionServer).Execute(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/generated.DeleteItemAction/Execute", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DeleteItemActionServer).Execute(ctx, req.(*DeleteItemActionExecuteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _DeleteItemAction_serviceDesc = grpc.ServiceDesc{ + ServiceName: "generated.DeleteItemAction", + HandlerType: (*DeleteItemActionServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "AppliesTo", + Handler: _DeleteItemAction_AppliesTo_Handler, + }, + { + MethodName: "Execute", + Handler: _DeleteItemAction_Execute_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "DeleteItemAction.proto", +} + +func init() { proto.RegisterFile("DeleteItemAction.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 253 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x41, 0x4b, 0xc3, 0x40, + 0x14, 0x84, 0x89, 0x4a, 0x25, 0xcf, 0x1e, 0xc2, 0x1e, 0x4a, 0x88, 0x20, 0x31, 0xa7, 0x8a, 0x92, + 0x43, 0xbd, 0x79, 0x2b, 0x58, 0xc5, 0x6b, 0xea, 0x1f, 0x48, 0x37, 0x63, 0x0d, 0x6e, 0xb2, 0xeb, + 0xee, 0x5b, 0xd0, 0xbf, 0xe7, 0x2f, 0x13, 0x63, 0x28, 0x35, 0x42, 0xdb, 0xdb, 0xbe, 0xdd, 0x99, + 0xf7, 0x31, 0x3b, 0x34, 0xb9, 0x87, 0x02, 0xe3, 0x89, 0xd1, 0xcc, 0x25, 0xd7, 0xba, 0xcd, 0x8d, + 0xd5, 0xac, 0x45, 0xb8, 0x46, 0x0b, 0x5b, 0x32, 0xaa, 0x64, 0xbc, 0x7c, 0x2d, 0x2d, 0xaa, 0xdf, + 0x87, 0xac, 0xa2, 0x8b, 0xa1, 0x65, 0xf1, 0x01, 0xe9, 0x19, 0x05, 0xde, 0x3d, 0x1c, 0x8b, 0x09, + 0x8d, 0x8c, 0xf2, 0xeb, 0xba, 0x8d, 0x83, 0x34, 0x98, 0x86, 0x45, 0x3f, 0x09, 0x41, 0x27, 0x35, + 0xa3, 0x89, 0x8f, 0xd2, 0x60, 0x3a, 0x2e, 0xba, 0xf3, 0x8f, 0x76, 0x55, 0xca, 0x37, 0x6f, 0xe2, + 0xe3, 0xee, 0xb6, 0x9f, 0xb2, 0x3b, 0x4a, 0x87, 0x94, 0xb9, 0x31, 0xaa, 0x86, 0x7b, 0xd6, 0x7b, + 0x38, 0x99, 0xa2, 0xcb, 0x1d, 0x5e, 0x67, 0x74, 0xeb, 0x20, 0x1e, 0x29, 0x2a, 0xe0, 0xb4, 0xb7, + 0x12, 0x4b, 0x28, 0x48, 0xd6, 0xb6, 0x5b, 0x73, 0x36, 0x3b, 0xcf, 0x37, 0xd1, 0xf3, 0xa1, 0xa4, + 0xf8, 0x67, 0x9a, 0x7d, 0x05, 0x14, 0x0d, 0x71, 0xe2, 0x85, 0xc2, 0x0d, 0x52, 0x5c, 0x6f, 0x2d, + 0xdc, 0x17, 0x2a, 0xb9, 0x39, 0x4c, 0xdc, 0xa7, 0x78, 0xa0, 0xd3, 0xfe, 0xf3, 0xc5, 0xd5, 0x0e, + 0xe3, 0xdf, 0x82, 0x92, 0x68, 0x4b, 0xba, 0x68, 0x0c, 0x7f, 0xae, 0x46, 0x5d, 0xb7, 0xb7, 0xdf, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x31, 0x0b, 0xd3, 0x0e, 0x02, 0x00, 0x00, +} diff --git a/pkg/plugin/generated/ObjectStore.pb.go b/pkg/plugin/generated/ObjectStore.pb.go index d93e615fd..121d70d45 100644 --- a/pkg/plugin/generated/ObjectStore.pb.go +++ b/pkg/plugin/generated/ObjectStore.pb.go @@ -27,7 +27,7 @@ type PutObjectRequest struct { func (m *PutObjectRequest) Reset() { *m = PutObjectRequest{} } func (m *PutObjectRequest) String() string { return proto.CompactTextString(m) } func (*PutObjectRequest) ProtoMessage() {} -func (*PutObjectRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } +func (*PutObjectRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } func (m *PutObjectRequest) GetPlugin() string { if m != nil { @@ -66,7 +66,7 @@ type ObjectExistsRequest struct { func (m *ObjectExistsRequest) Reset() { *m = ObjectExistsRequest{} } func (m *ObjectExistsRequest) String() string { return proto.CompactTextString(m) } func (*ObjectExistsRequest) ProtoMessage() {} -func (*ObjectExistsRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } +func (*ObjectExistsRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } func (m *ObjectExistsRequest) GetPlugin() string { if m != nil { @@ -96,7 +96,7 @@ type ObjectExistsResponse struct { func (m *ObjectExistsResponse) Reset() { *m = ObjectExistsResponse{} } func (m *ObjectExistsResponse) String() string { return proto.CompactTextString(m) } func (*ObjectExistsResponse) ProtoMessage() {} -func (*ObjectExistsResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } +func (*ObjectExistsResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{2} } func (m *ObjectExistsResponse) GetExists() bool { if m != nil { @@ -114,7 +114,7 @@ type GetObjectRequest struct { func (m *GetObjectRequest) Reset() { *m = GetObjectRequest{} } func (m *GetObjectRequest) String() string { return proto.CompactTextString(m) } func (*GetObjectRequest) ProtoMessage() {} -func (*GetObjectRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } +func (*GetObjectRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{3} } func (m *GetObjectRequest) GetPlugin() string { if m != nil { @@ -144,7 +144,7 @@ type Bytes struct { func (m *Bytes) Reset() { *m = Bytes{} } func (m *Bytes) String() string { return proto.CompactTextString(m) } func (*Bytes) ProtoMessage() {} -func (*Bytes) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } +func (*Bytes) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{4} } func (m *Bytes) GetData() []byte { if m != nil { @@ -163,7 +163,7 @@ type ListCommonPrefixesRequest struct { func (m *ListCommonPrefixesRequest) Reset() { *m = ListCommonPrefixesRequest{} } func (m *ListCommonPrefixesRequest) String() string { return proto.CompactTextString(m) } func (*ListCommonPrefixesRequest) ProtoMessage() {} -func (*ListCommonPrefixesRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } +func (*ListCommonPrefixesRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{5} } func (m *ListCommonPrefixesRequest) GetPlugin() string { if m != nil { @@ -200,7 +200,7 @@ type ListCommonPrefixesResponse struct { func (m *ListCommonPrefixesResponse) Reset() { *m = ListCommonPrefixesResponse{} } func (m *ListCommonPrefixesResponse) String() string { return proto.CompactTextString(m) } func (*ListCommonPrefixesResponse) ProtoMessage() {} -func (*ListCommonPrefixesResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } +func (*ListCommonPrefixesResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{6} } func (m *ListCommonPrefixesResponse) GetPrefixes() []string { if m != nil { @@ -218,7 +218,7 @@ type ListObjectsRequest struct { func (m *ListObjectsRequest) Reset() { *m = ListObjectsRequest{} } func (m *ListObjectsRequest) String() string { return proto.CompactTextString(m) } func (*ListObjectsRequest) ProtoMessage() {} -func (*ListObjectsRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } +func (*ListObjectsRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{7} } func (m *ListObjectsRequest) GetPlugin() string { if m != nil { @@ -248,7 +248,7 @@ type ListObjectsResponse struct { func (m *ListObjectsResponse) Reset() { *m = ListObjectsResponse{} } func (m *ListObjectsResponse) String() string { return proto.CompactTextString(m) } func (*ListObjectsResponse) ProtoMessage() {} -func (*ListObjectsResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } +func (*ListObjectsResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{8} } func (m *ListObjectsResponse) GetKeys() []string { if m != nil { @@ -266,7 +266,7 @@ type DeleteObjectRequest struct { func (m *DeleteObjectRequest) Reset() { *m = DeleteObjectRequest{} } func (m *DeleteObjectRequest) String() string { return proto.CompactTextString(m) } func (*DeleteObjectRequest) ProtoMessage() {} -func (*DeleteObjectRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} } +func (*DeleteObjectRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{9} } func (m *DeleteObjectRequest) GetPlugin() string { if m != nil { @@ -299,7 +299,7 @@ type CreateSignedURLRequest struct { func (m *CreateSignedURLRequest) Reset() { *m = CreateSignedURLRequest{} } func (m *CreateSignedURLRequest) String() string { return proto.CompactTextString(m) } func (*CreateSignedURLRequest) ProtoMessage() {} -func (*CreateSignedURLRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } +func (*CreateSignedURLRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{10} } func (m *CreateSignedURLRequest) GetPlugin() string { if m != nil { @@ -336,7 +336,7 @@ type CreateSignedURLResponse struct { func (m *CreateSignedURLResponse) Reset() { *m = CreateSignedURLResponse{} } func (m *CreateSignedURLResponse) String() string { return proto.CompactTextString(m) } func (*CreateSignedURLResponse) ProtoMessage() {} -func (*CreateSignedURLResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} } +func (*CreateSignedURLResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{11} } func (m *CreateSignedURLResponse) GetUrl() string { if m != nil { @@ -353,7 +353,7 @@ type ObjectStoreInitRequest struct { func (m *ObjectStoreInitRequest) Reset() { *m = ObjectStoreInitRequest{} } func (m *ObjectStoreInitRequest) String() string { return proto.CompactTextString(m) } func (*ObjectStoreInitRequest) ProtoMessage() {} -func (*ObjectStoreInitRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} } +func (*ObjectStoreInitRequest) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{12} } func (m *ObjectStoreInitRequest) GetPlugin() string { if m != nil { @@ -750,9 +750,9 @@ var _ObjectStore_serviceDesc = grpc.ServiceDesc{ Metadata: "ObjectStore.proto", } -func init() { proto.RegisterFile("ObjectStore.proto", fileDescriptor1) } +func init() { proto.RegisterFile("ObjectStore.proto", fileDescriptor2) } -var fileDescriptor1 = []byte{ +var fileDescriptor2 = []byte{ // 577 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x6e, 0xd3, 0x40, 0x10, 0xd6, 0xc6, 0x69, 0x54, 0x4f, 0x22, 0x61, 0xb6, 0x55, 0x30, 0x2e, 0x94, 0xb0, 0x02, 0x29, diff --git a/pkg/plugin/generated/PluginLister.pb.go b/pkg/plugin/generated/PluginLister.pb.go index 43fb4d2d1..0f4fe7c87 100644 --- a/pkg/plugin/generated/PluginLister.pb.go +++ b/pkg/plugin/generated/PluginLister.pb.go @@ -26,7 +26,7 @@ type PluginIdentifier struct { func (m *PluginIdentifier) Reset() { *m = PluginIdentifier{} } func (m *PluginIdentifier) String() string { return proto.CompactTextString(m) } func (*PluginIdentifier) ProtoMessage() {} -func (*PluginIdentifier) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{0} } +func (*PluginIdentifier) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} } func (m *PluginIdentifier) GetCommand() string { if m != nil { @@ -56,7 +56,7 @@ type ListPluginsResponse struct { func (m *ListPluginsResponse) Reset() { *m = ListPluginsResponse{} } func (m *ListPluginsResponse) String() string { return proto.CompactTextString(m) } func (*ListPluginsResponse) ProtoMessage() {} -func (*ListPluginsResponse) Descriptor() ([]byte, []int) { return fileDescriptor2, []int{1} } +func (*ListPluginsResponse) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{1} } func (m *ListPluginsResponse) GetPlugins() []*PluginIdentifier { if m != nil { @@ -142,9 +142,9 @@ var _PluginLister_serviceDesc = grpc.ServiceDesc{ Metadata: "PluginLister.proto", } -func init() { proto.RegisterFile("PluginLister.proto", fileDescriptor2) } +func init() { proto.RegisterFile("PluginLister.proto", fileDescriptor3) } -var fileDescriptor2 = []byte{ +var fileDescriptor3 = []byte{ // 201 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x0a, 0xc8, 0x29, 0x4d, 0xcf, 0xcc, 0xf3, 0xc9, 0x2c, 0x2e, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, diff --git a/pkg/plugin/generated/RestoreItemAction.pb.go b/pkg/plugin/generated/RestoreItemAction.pb.go index a736defda..63a92b4c2 100644 --- a/pkg/plugin/generated/RestoreItemAction.pb.go +++ b/pkg/plugin/generated/RestoreItemAction.pb.go @@ -28,7 +28,7 @@ func (m *RestoreItemActionExecuteRequest) Reset() { *m = RestoreItemActi func (m *RestoreItemActionExecuteRequest) String() string { return proto.CompactTextString(m) } func (*RestoreItemActionExecuteRequest) ProtoMessage() {} func (*RestoreItemActionExecuteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor3, []int{0} + return fileDescriptor4, []int{0} } func (m *RestoreItemActionExecuteRequest) GetPlugin() string { @@ -69,7 +69,7 @@ func (m *RestoreItemActionExecuteResponse) Reset() { *m = RestoreItemAct func (m *RestoreItemActionExecuteResponse) String() string { return proto.CompactTextString(m) } func (*RestoreItemActionExecuteResponse) ProtoMessage() {} func (*RestoreItemActionExecuteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor3, []int{1} + return fileDescriptor4, []int{1} } func (m *RestoreItemActionExecuteResponse) GetItem() []byte { @@ -101,7 +101,7 @@ func (m *RestoreItemActionAppliesToRequest) Reset() { *m = RestoreItemAc func (m *RestoreItemActionAppliesToRequest) String() string { return proto.CompactTextString(m) } func (*RestoreItemActionAppliesToRequest) ProtoMessage() {} func (*RestoreItemActionAppliesToRequest) Descriptor() ([]byte, []int) { - return fileDescriptor3, []int{2} + return fileDescriptor4, []int{2} } func (m *RestoreItemActionAppliesToRequest) GetPlugin() string { @@ -119,7 +119,7 @@ func (m *RestoreItemActionAppliesToResponse) Reset() { *m = RestoreItemA func (m *RestoreItemActionAppliesToResponse) String() string { return proto.CompactTextString(m) } func (*RestoreItemActionAppliesToResponse) ProtoMessage() {} func (*RestoreItemActionAppliesToResponse) Descriptor() ([]byte, []int) { - return fileDescriptor3, []int{3} + return fileDescriptor4, []int{3} } func (m *RestoreItemActionAppliesToResponse) GetResourceSelector() *ResourceSelector { @@ -241,9 +241,9 @@ var _RestoreItemAction_serviceDesc = grpc.ServiceDesc{ Metadata: "RestoreItemAction.proto", } -func init() { proto.RegisterFile("RestoreItemAction.proto", fileDescriptor3) } +func init() { proto.RegisterFile("RestoreItemAction.proto", fileDescriptor4) } -var fileDescriptor3 = []byte{ +var fileDescriptor4 = []byte{ // 332 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0xdd, 0x4e, 0xc2, 0x30, 0x14, 0x4e, 0x81, 0x80, 0x1c, 0x88, 0x3f, 0xbd, 0xd0, 0x06, 0x63, 0x9c, 0xbb, 0x30, 0xc4, 0x1f, diff --git a/pkg/plugin/generated/Shared.pb.go b/pkg/plugin/generated/Shared.pb.go index 84d79d6bb..29714972e 100644 --- a/pkg/plugin/generated/Shared.pb.go +++ b/pkg/plugin/generated/Shared.pb.go @@ -18,7 +18,7 @@ type Empty struct { func (m *Empty) Reset() { *m = Empty{} } func (m *Empty) String() string { return proto.CompactTextString(m) } func (*Empty) ProtoMessage() {} -func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{0} } +func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } type Stack struct { Frames []*StackFrame `protobuf:"bytes,1,rep,name=frames" json:"frames,omitempty"` @@ -27,7 +27,7 @@ type Stack struct { func (m *Stack) Reset() { *m = Stack{} } func (m *Stack) String() string { return proto.CompactTextString(m) } func (*Stack) ProtoMessage() {} -func (*Stack) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{1} } +func (*Stack) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{1} } func (m *Stack) GetFrames() []*StackFrame { if m != nil { @@ -45,7 +45,7 @@ type StackFrame struct { func (m *StackFrame) Reset() { *m = StackFrame{} } func (m *StackFrame) String() string { return proto.CompactTextString(m) } func (*StackFrame) ProtoMessage() {} -func (*StackFrame) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{2} } +func (*StackFrame) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{2} } func (m *StackFrame) GetFile() string { if m != nil { @@ -78,7 +78,7 @@ type ResourceIdentifier struct { func (m *ResourceIdentifier) Reset() { *m = ResourceIdentifier{} } func (m *ResourceIdentifier) String() string { return proto.CompactTextString(m) } func (*ResourceIdentifier) ProtoMessage() {} -func (*ResourceIdentifier) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{3} } +func (*ResourceIdentifier) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{3} } func (m *ResourceIdentifier) GetGroup() string { if m != nil { @@ -119,7 +119,7 @@ type ResourceSelector struct { func (m *ResourceSelector) Reset() { *m = ResourceSelector{} } func (m *ResourceSelector) String() string { return proto.CompactTextString(m) } func (*ResourceSelector) ProtoMessage() {} -func (*ResourceSelector) Descriptor() ([]byte, []int) { return fileDescriptor4, []int{4} } +func (*ResourceSelector) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{4} } func (m *ResourceSelector) GetIncludedNamespaces() []string { if m != nil { @@ -164,9 +164,9 @@ func init() { proto.RegisterType((*ResourceSelector)(nil), "generated.ResourceSelector") } -func init() { proto.RegisterFile("Shared.proto", fileDescriptor4) } +func init() { proto.RegisterFile("Shared.proto", fileDescriptor5) } -var fileDescriptor4 = []byte{ +var fileDescriptor5 = []byte{ // 294 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xc1, 0x4e, 0xb5, 0x30, 0x10, 0x85, 0xc3, 0x05, 0xee, 0xff, 0x33, 0xba, 0xd0, 0x46, 0x93, 0xc6, 0xb8, 0x20, 0xac, 0x58, diff --git a/pkg/plugin/generated/VolumeSnapshotter.pb.go b/pkg/plugin/generated/VolumeSnapshotter.pb.go index b40234c03..b814bae9a 100644 --- a/pkg/plugin/generated/VolumeSnapshotter.pb.go +++ b/pkg/plugin/generated/VolumeSnapshotter.pb.go @@ -28,7 +28,7 @@ type CreateVolumeRequest struct { func (m *CreateVolumeRequest) Reset() { *m = CreateVolumeRequest{} } func (m *CreateVolumeRequest) String() string { return proto.CompactTextString(m) } func (*CreateVolumeRequest) ProtoMessage() {} -func (*CreateVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} } +func (*CreateVolumeRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{0} } func (m *CreateVolumeRequest) GetPlugin() string { if m != nil { @@ -72,7 +72,7 @@ type CreateVolumeResponse struct { func (m *CreateVolumeResponse) Reset() { *m = CreateVolumeResponse{} } func (m *CreateVolumeResponse) String() string { return proto.CompactTextString(m) } func (*CreateVolumeResponse) ProtoMessage() {} -func (*CreateVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{1} } +func (*CreateVolumeResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{1} } func (m *CreateVolumeResponse) GetVolumeID() string { if m != nil { @@ -90,7 +90,7 @@ type GetVolumeInfoRequest struct { func (m *GetVolumeInfoRequest) Reset() { *m = GetVolumeInfoRequest{} } func (m *GetVolumeInfoRequest) String() string { return proto.CompactTextString(m) } func (*GetVolumeInfoRequest) ProtoMessage() {} -func (*GetVolumeInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{2} } +func (*GetVolumeInfoRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{2} } func (m *GetVolumeInfoRequest) GetPlugin() string { if m != nil { @@ -121,7 +121,7 @@ type GetVolumeInfoResponse struct { func (m *GetVolumeInfoResponse) Reset() { *m = GetVolumeInfoResponse{} } func (m *GetVolumeInfoResponse) String() string { return proto.CompactTextString(m) } func (*GetVolumeInfoResponse) ProtoMessage() {} -func (*GetVolumeInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{3} } +func (*GetVolumeInfoResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{3} } func (m *GetVolumeInfoResponse) GetVolumeType() string { if m != nil { @@ -147,7 +147,7 @@ type CreateSnapshotRequest struct { func (m *CreateSnapshotRequest) Reset() { *m = CreateSnapshotRequest{} } func (m *CreateSnapshotRequest) String() string { return proto.CompactTextString(m) } func (*CreateSnapshotRequest) ProtoMessage() {} -func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{4} } +func (*CreateSnapshotRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{4} } func (m *CreateSnapshotRequest) GetPlugin() string { if m != nil { @@ -184,7 +184,7 @@ type CreateSnapshotResponse struct { func (m *CreateSnapshotResponse) Reset() { *m = CreateSnapshotResponse{} } func (m *CreateSnapshotResponse) String() string { return proto.CompactTextString(m) } func (*CreateSnapshotResponse) ProtoMessage() {} -func (*CreateSnapshotResponse) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{5} } +func (*CreateSnapshotResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{5} } func (m *CreateSnapshotResponse) GetSnapshotID() string { if m != nil { @@ -201,7 +201,7 @@ type DeleteSnapshotRequest struct { func (m *DeleteSnapshotRequest) Reset() { *m = DeleteSnapshotRequest{} } func (m *DeleteSnapshotRequest) String() string { return proto.CompactTextString(m) } func (*DeleteSnapshotRequest) ProtoMessage() {} -func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{6} } +func (*DeleteSnapshotRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{6} } func (m *DeleteSnapshotRequest) GetPlugin() string { if m != nil { @@ -225,7 +225,7 @@ type GetVolumeIDRequest struct { func (m *GetVolumeIDRequest) Reset() { *m = GetVolumeIDRequest{} } func (m *GetVolumeIDRequest) String() string { return proto.CompactTextString(m) } func (*GetVolumeIDRequest) ProtoMessage() {} -func (*GetVolumeIDRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{7} } +func (*GetVolumeIDRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{7} } func (m *GetVolumeIDRequest) GetPlugin() string { if m != nil { @@ -248,7 +248,7 @@ type GetVolumeIDResponse struct { func (m *GetVolumeIDResponse) Reset() { *m = GetVolumeIDResponse{} } func (m *GetVolumeIDResponse) String() string { return proto.CompactTextString(m) } func (*GetVolumeIDResponse) ProtoMessage() {} -func (*GetVolumeIDResponse) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{8} } +func (*GetVolumeIDResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{8} } func (m *GetVolumeIDResponse) GetVolumeID() string { if m != nil { @@ -266,7 +266,7 @@ type SetVolumeIDRequest struct { func (m *SetVolumeIDRequest) Reset() { *m = SetVolumeIDRequest{} } func (m *SetVolumeIDRequest) String() string { return proto.CompactTextString(m) } func (*SetVolumeIDRequest) ProtoMessage() {} -func (*SetVolumeIDRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{9} } +func (*SetVolumeIDRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{9} } func (m *SetVolumeIDRequest) GetPlugin() string { if m != nil { @@ -296,7 +296,7 @@ type SetVolumeIDResponse struct { func (m *SetVolumeIDResponse) Reset() { *m = SetVolumeIDResponse{} } func (m *SetVolumeIDResponse) String() string { return proto.CompactTextString(m) } func (*SetVolumeIDResponse) ProtoMessage() {} -func (*SetVolumeIDResponse) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{10} } +func (*SetVolumeIDResponse) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{10} } func (m *SetVolumeIDResponse) GetPersistentVolume() []byte { if m != nil { @@ -313,7 +313,7 @@ type VolumeSnapshotterInitRequest struct { func (m *VolumeSnapshotterInitRequest) Reset() { *m = VolumeSnapshotterInitRequest{} } func (m *VolumeSnapshotterInitRequest) String() string { return proto.CompactTextString(m) } func (*VolumeSnapshotterInitRequest) ProtoMessage() {} -func (*VolumeSnapshotterInitRequest) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{11} } +func (*VolumeSnapshotterInitRequest) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{11} } func (m *VolumeSnapshotterInitRequest) GetPlugin() string { if m != nil { @@ -614,9 +614,9 @@ var _VolumeSnapshotter_serviceDesc = grpc.ServiceDesc{ Metadata: "VolumeSnapshotter.proto", } -func init() { proto.RegisterFile("VolumeSnapshotter.proto", fileDescriptor5) } +func init() { proto.RegisterFile("VolumeSnapshotter.proto", fileDescriptor6) } -var fileDescriptor5 = []byte{ +var fileDescriptor6 = []byte{ // 566 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xc1, 0x6e, 0xd3, 0x40, 0x10, 0xd5, 0xda, 0x6e, 0x44, 0x26, 0xa5, 0x0a, 0x9b, 0xa4, 0x58, 0x16, 0x04, 0xe3, 0x0b, 0x51, diff --git a/pkg/plugin/mocks/manager.go b/pkg/plugin/mocks/manager.go index ef6beea7b..ebf09de96 100644 --- a/pkg/plugin/mocks/manager.go +++ b/pkg/plugin/mocks/manager.go @@ -1,25 +1,10 @@ -/* -Copyright 2018 the Velero contributors. +// Code generated by mockery v2.1.0. DO NOT EDIT. -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. -*/ -// Code generated by mockery v1.0.0. DO NOT EDIT. package mocks import ( mock "github.com/stretchr/testify/mock" - - "github.com/vmware-tanzu/velero/pkg/plugin/velero" + velero "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) // Manager is an autogenerated mock type for the Manager type @@ -78,16 +63,16 @@ func (_m *Manager) GetBackupItemActions() ([]velero.BackupItemAction, error) { return r0, r1 } -// GetVolumeSnapshotter provides a mock function with given fields: name -func (_m *Manager) GetVolumeSnapshotter(name string) (velero.VolumeSnapshotter, error) { +// GetDeleteItemAction provides a mock function with given fields: name +func (_m *Manager) GetDeleteItemAction(name string) (velero.DeleteItemAction, error) { ret := _m.Called(name) - var r0 velero.VolumeSnapshotter - if rf, ok := ret.Get(0).(func(string) velero.VolumeSnapshotter); ok { + var r0 velero.DeleteItemAction + if rf, ok := ret.Get(0).(func(string) velero.DeleteItemAction); ok { r0 = rf(name) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(velero.VolumeSnapshotter) + r0 = ret.Get(0).(velero.DeleteItemAction) } } @@ -101,6 +86,29 @@ func (_m *Manager) GetVolumeSnapshotter(name string) (velero.VolumeSnapshotter, return r0, r1 } +// GetDeleteItemActions provides a mock function with given fields: +func (_m *Manager) GetDeleteItemActions() ([]velero.DeleteItemAction, error) { + ret := _m.Called() + + var r0 []velero.DeleteItemAction + if rf, ok := ret.Get(0).(func() []velero.DeleteItemAction); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]velero.DeleteItemAction) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetObjectStore provides a mock function with given fields: name func (_m *Manager) GetObjectStore(name string) (velero.ObjectStore, error) { ret := _m.Called(name) @@ -169,3 +177,26 @@ func (_m *Manager) GetRestoreItemActions() ([]velero.RestoreItemAction, error) { return r0, r1 } + +// GetVolumeSnapshotter provides a mock function with given fields: name +func (_m *Manager) GetVolumeSnapshotter(name string) (velero.VolumeSnapshotter, error) { + ret := _m.Called(name) + + var r0 velero.VolumeSnapshotter + if rf, ok := ret.Get(0).(func(string) velero.VolumeSnapshotter); ok { + r0 = rf(name) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(velero.VolumeSnapshotter) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(name) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/pkg/plugin/proto/DeleteItemAction.proto b/pkg/plugin/proto/DeleteItemAction.proto new file mode 100644 index 000000000..48c38817e --- /dev/null +++ b/pkg/plugin/proto/DeleteItemAction.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; +package generated; + +import "Shared.proto"; + +message DeleteItemActionExecuteRequest { + string plugin = 1; + bytes item = 2; + bytes backup = 3; +} + +service DeleteItemAction { + rpc AppliesTo(DeleteItemActionAppliesToRequest) returns (DeleteItemActionAppliesToResponse); + rpc Execute(DeleteItemActionExecuteRequest) returns (Empty); +} + +message DeleteItemActionAppliesToRequest { + string plugin = 1; +} + +message DeleteItemActionAppliesToResponse { + ResourceSelector ResourceSelector = 1; +} diff --git a/pkg/plugin/velero/delete_item_action.go b/pkg/plugin/velero/delete_item_action.go new file mode 100644 index 000000000..e3e7d9259 --- /dev/null +++ b/pkg/plugin/velero/delete_item_action.go @@ -0,0 +1,45 @@ +/* +Copyright 2020 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 velero + +import ( + "k8s.io/apimachinery/pkg/runtime" + + velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" +) + +// DeleteItemAction is an actor that performs an operation on an individual item being restored. +type DeleteItemAction interface { + // AppliesTo returns information about which resources this action should be invoked for. + // A DeleteItemAction's Execute function will only be invoked on items that match the returned + // selector. A zero-valued ResourceSelector matches all resources. + AppliesTo() (ResourceSelector, error) + + // Execute allows the ItemAction to perform arbitrary logic with the item being deleted. + // An error should be returned if there were problems with the deletion process, but the + // overall deletion process cannot be stopped. + // Returned errors are logged. + Execute(input *DeleteItemActionExecuteInput) error +} + +// DeleteItemActionExecuteInput contains the input parameters for the ItemAction's Execute function. +type DeleteItemActionExecuteInput struct { + // Item is the item taken from the pristine backed up version of resource. + Item runtime.Unstructured + // Backup is the representation of the restore resource processed by Velero. + Backup *velerov1api.Backup +} diff --git a/pkg/plugin/velero/mocks/DeleteItemAction.go b/pkg/plugin/velero/mocks/DeleteItemAction.go new file mode 100644 index 000000000..101e04fde --- /dev/null +++ b/pkg/plugin/velero/mocks/DeleteItemAction.go @@ -0,0 +1,48 @@ +// Code generated by mockery v2.1.0. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + velero "github.com/vmware-tanzu/velero/pkg/plugin/velero" +) + +// DeleteItemAction is an autogenerated mock type for the DeleteItemAction type +type DeleteItemAction struct { + mock.Mock +} + +// AppliesTo provides a mock function with given fields: +func (_m *DeleteItemAction) AppliesTo() (velero.ResourceSelector, error) { + ret := _m.Called() + + var r0 velero.ResourceSelector + if rf, ok := ret.Get(0).(func() velero.ResourceSelector); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(velero.ResourceSelector) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Execute provides a mock function with given fields: input +func (_m *DeleteItemAction) Execute(input *velero.DeleteItemActionExecuteInput) error { + ret := _m.Called(input) + + var r0 error + if rf, ok := ret.Get(0).(func(*velero.DeleteItemActionExecuteInput) error); ok { + r0 = rf(input) + } else { + r0 = ret.Error(0) + } + + return r0 +}