Create hook package (#2734)

* Move pkg/backup/item_hook_handler to internal/hoo

Signed-off-by: Nolan Brubaker <brubakern@vmware.com>

* Add internal packages to test target

Signed-off-by: Nolan Brubaker <brubakern@vmware.com>
pull/2758/head
Nolan Brubaker 2020-07-22 17:26:14 -04:00 committed by GitHub
parent e83ec79df3
commit bbcbde084d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 116 additions and 109 deletions

View File

@ -0,0 +1 @@
Move pkg/backup/item_hook_handlers.go to internal/hook

View File

@ -1,6 +1,7 @@
#!/bin/bash
# Copyright 2016 The Kubernetes Authors.
# Modifications 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.
@ -23,6 +24,7 @@ export CGO_ENABLED=0
TARGETS=(
./cmd/...
./pkg/...
./internal/...
)
if [[ ${#@} -ne 0 ]]; then

View File

@ -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.
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package backup
package hook
import (
"encoding/json"
@ -38,35 +38,35 @@ import (
type hookPhase string
const (
hookPhasePre hookPhase = "pre"
hookPhasePost hookPhase = "post"
PhasePre hookPhase = "pre"
PhasePost hookPhase = "post"
)
// itemHookHandler invokes hooks for an item.
type itemHookHandler interface {
// handleHooks invokes hooks for an item. If the item is a pod and the appropriate annotations exist
// ItemHookHandler invokes hooks for an item.
type ItemHookHandler interface {
// HandleHooks invokes hooks for an item. If the item is a pod and the appropriate annotations exist
// to specify a hook, that is executed. Otherwise, this looks at the backup context's Backup to
// determine if there are any hooks relevant to the item, taking into account the hook spec's
// namespaces, resources, and label selector.
handleHooks(
HandleHooks(
log logrus.FieldLogger,
groupResource schema.GroupResource,
obj runtime.Unstructured,
resourceHooks []resourceHook,
resourceHooks []ResourceHook,
phase hookPhase,
) error
}
// defaultItemHookHandler is the default itemHookHandler.
type defaultItemHookHandler struct {
podCommandExecutor podexec.PodCommandExecutor
// DefaultItemHookHandler is the default itemHookHandler.
type DefaultItemHookHandler struct {
PodCommandExecutor podexec.PodCommandExecutor
}
func (h *defaultItemHookHandler) handleHooks(
func (h *DefaultItemHookHandler) HandleHooks(
log logrus.FieldLogger,
groupResource schema.GroupResource,
obj runtime.Unstructured,
resourceHooks []resourceHook,
resourceHooks []ResourceHook,
phase hookPhase,
) error {
// We only support hooks on pods right now
@ -84,7 +84,7 @@ func (h *defaultItemHookHandler) handleHooks(
// If the pod has the hook specified via annotations, that takes priority.
hookFromAnnotations := getPodExecHookFromAnnotations(metadata.GetAnnotations(), phase, log)
if phase == hookPhasePre && hookFromAnnotations == nil {
if phase == PhasePre && hookFromAnnotations == nil {
// See if the pod has the legacy hook annotation keys (i.e. without a phase specified)
hookFromAnnotations = getPodExecHookFromAnnotations(metadata.GetAnnotations(), "", log)
}
@ -96,7 +96,7 @@ func (h *defaultItemHookHandler) handleHooks(
"hookPhase": phase,
},
)
if err := h.podCommandExecutor.ExecutePodCommand(hookLog, obj.UnstructuredContent(), namespace, name, "<from-annotation>", hookFromAnnotations); err != nil {
if err := h.PodCommandExecutor.ExecutePodCommand(hookLog, obj.UnstructuredContent(), namespace, name, "<from-annotation>", hookFromAnnotations); err != nil {
hookLog.WithError(err).Error("Error executing hook")
if hookFromAnnotations.OnError == api.HookErrorModeFail {
return err
@ -114,10 +114,10 @@ func (h *defaultItemHookHandler) handleHooks(
}
var hooks []api.BackupResourceHook
if phase == hookPhasePre {
hooks = resourceHook.pre
if phase == PhasePre {
hooks = resourceHook.Pre
} else {
hooks = resourceHook.post
hooks = resourceHook.Post
}
for _, hook := range hooks {
if groupResource == kuberesource.Pods {
@ -129,7 +129,7 @@ func (h *defaultItemHookHandler) handleHooks(
"hookPhase": phase,
},
)
err := h.podCommandExecutor.ExecutePodCommand(hookLog, obj.UnstructuredContent(), namespace, name, resourceHook.name, hook.Exec)
err := h.PodCommandExecutor.ExecutePodCommand(hookLog, obj.UnstructuredContent(), namespace, name, resourceHook.Name, hook.Exec)
if err != nil {
hookLog.WithError(err).Error("Error executing hook")
if hook.Exec.OnError == api.HookErrorModeFail {
@ -205,23 +205,24 @@ func getPodExecHookFromAnnotations(annotations map[string]string, phase hookPhas
}
}
type resourceHook struct {
name string
namespaces *collections.IncludesExcludes
resources *collections.IncludesExcludes
labelSelector labels.Selector
pre []api.BackupResourceHook
post []api.BackupResourceHook
// ResourceHook is a hook for a given resource.
type ResourceHook struct {
Name string
Namespaces *collections.IncludesExcludes
Resources *collections.IncludesExcludes
LabelSelector labels.Selector
Pre []api.BackupResourceHook
Post []api.BackupResourceHook
}
func (r resourceHook) applicableTo(groupResource schema.GroupResource, namespace string, labels labels.Set) bool {
if r.namespaces != nil && !r.namespaces.ShouldInclude(namespace) {
func (r ResourceHook) applicableTo(groupResource schema.GroupResource, namespace string, labels labels.Set) bool {
if r.Namespaces != nil && !r.Namespaces.ShouldInclude(namespace) {
return false
}
if r.resources != nil && !r.resources.ShouldInclude(groupResource.String()) {
if r.Resources != nil && !r.Resources.ShouldInclude(groupResource.String()) {
return false
}
if r.labelSelector != nil && !r.labelSelector.Matches(labels) {
if r.LabelSelector != nil && !r.LabelSelector.Matches(labels) {
return false
}
return true

View File

@ -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.
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package backup
package hook
import (
"fmt"
@ -40,7 +40,7 @@ type mockItemHookHandler struct {
mock.Mock
}
func (h *mockItemHookHandler) handleHooks(log logrus.FieldLogger, groupResource schema.GroupResource, obj runtime.Unstructured, resourceHooks []resourceHook, phase hookPhase) error {
func (h *mockItemHookHandler) HandleHooks(log logrus.FieldLogger, groupResource schema.GroupResource, obj runtime.Unstructured, resourceHooks []ResourceHook, phase hookPhase) error {
args := h.Called(log, groupResource, obj, resourceHooks, phase)
return args.Error(0)
}
@ -50,7 +50,7 @@ func TestHandleHooksSkips(t *testing.T) {
name string
groupResource string
item runtime.Unstructured
hooks []resourceHook
hooks []ResourceHook
}{
{
name: "not a pod",
@ -89,22 +89,22 @@ func TestHandleHooksSkips(t *testing.T) {
}
`,
),
hooks: []resourceHook{
hooks: []ResourceHook{
{
name: "ns exclude",
namespaces: collections.NewIncludesExcludes().Excludes("ns"),
Name: "ns exclude",
Namespaces: collections.NewIncludesExcludes().Excludes("ns"),
},
{
name: "resource exclude",
resources: collections.NewIncludesExcludes().Includes("widgets.group"),
Name: "resource exclude",
Resources: collections.NewIncludesExcludes().Includes("widgets.group"),
},
{
name: "label selector mismatch",
labelSelector: parseLabelSelectorOrDie("color=green"),
Name: "label selector mismatch",
LabelSelector: parseLabelSelectorOrDie("color=green"),
},
{
name: "missing exec hook",
pre: []v1.BackupResourceHook{
Name: "missing exec hook",
Pre: []v1.BackupResourceHook{
{},
{},
},
@ -118,12 +118,12 @@ func TestHandleHooksSkips(t *testing.T) {
podCommandExecutor := &velerotest.MockPodCommandExecutor{}
defer podCommandExecutor.AssertExpectations(t)
h := &defaultItemHookHandler{
podCommandExecutor: podCommandExecutor,
h := &DefaultItemHookHandler{
PodCommandExecutor: podCommandExecutor,
}
groupResource := schema.ParseGroupResource(test.groupResource)
err := h.handleHooks(velerotest.NewLogger(), groupResource, test.item, test.hooks, hookPhasePre)
err := h.HandleHooks(velerotest.NewLogger(), groupResource, test.item, test.hooks, PhasePre)
assert.NoError(t, err)
})
}
@ -135,7 +135,7 @@ func TestHandleHooks(t *testing.T) {
phase hookPhase
groupResource string
item runtime.Unstructured
hooks []resourceHook
hooks []ResourceHook
hookErrorsByContainer map[string]error
expectedError error
expectedPodHook *v1.ExecHook
@ -143,7 +143,7 @@ func TestHandleHooks(t *testing.T) {
}{
{
name: "pod, no annotation, spec (multiple pre hooks) = run spec",
phase: hookPhasePre,
phase: PhasePre,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -154,10 +154,10 @@ func TestHandleHooks(t *testing.T) {
"name": "name"
}
}`),
hooks: []resourceHook{
hooks: []ResourceHook{
{
name: "hook1",
pre: []v1.BackupResourceHook{
Name: "hook1",
Pre: []v1.BackupResourceHook{
{
Exec: &v1.ExecHook{
Container: "1a",
@ -173,8 +173,8 @@ func TestHandleHooks(t *testing.T) {
},
},
{
name: "hook2",
pre: []v1.BackupResourceHook{
Name: "hook2",
Pre: []v1.BackupResourceHook{
{
Exec: &v1.ExecHook{
Container: "2a",
@ -193,7 +193,7 @@ func TestHandleHooks(t *testing.T) {
},
{
name: "pod, no annotation, spec (multiple post hooks) = run spec",
phase: hookPhasePost,
phase: PhasePost,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -204,10 +204,10 @@ func TestHandleHooks(t *testing.T) {
"name": "name"
}
}`),
hooks: []resourceHook{
hooks: []ResourceHook{
{
name: "hook1",
post: []v1.BackupResourceHook{
Name: "hook1",
Post: []v1.BackupResourceHook{
{
Exec: &v1.ExecHook{
Container: "1a",
@ -223,8 +223,8 @@ func TestHandleHooks(t *testing.T) {
},
},
{
name: "hook2",
post: []v1.BackupResourceHook{
Name: "hook2",
Post: []v1.BackupResourceHook{
{
Exec: &v1.ExecHook{
Container: "2a",
@ -243,7 +243,7 @@ func TestHandleHooks(t *testing.T) {
},
{
name: "pod, annotation (legacy), no spec = run annotation",
phase: hookPhasePre,
phase: PhasePre,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -265,7 +265,7 @@ func TestHandleHooks(t *testing.T) {
},
{
name: "pod, annotation (pre), no spec = run annotation",
phase: hookPhasePre,
phase: PhasePre,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -287,7 +287,7 @@ func TestHandleHooks(t *testing.T) {
},
{
name: "pod, annotation (post), no spec = run annotation",
phase: hookPhasePost,
phase: PhasePost,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -309,7 +309,7 @@ func TestHandleHooks(t *testing.T) {
},
{
name: "pod, annotation & spec = run annotation",
phase: hookPhasePre,
phase: PhasePre,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -328,10 +328,10 @@ func TestHandleHooks(t *testing.T) {
Container: "c",
Command: []string{"/bin/ls"},
},
hooks: []resourceHook{
hooks: []ResourceHook{
{
name: "hook1",
pre: []v1.BackupResourceHook{
Name: "hook1",
Pre: []v1.BackupResourceHook{
{
Exec: &v1.ExecHook{
Container: "1a",
@ -344,7 +344,7 @@ func TestHandleHooks(t *testing.T) {
},
{
name: "pod, annotation, onError=fail = return error",
phase: hookPhasePre,
phase: PhasePre,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -370,7 +370,7 @@ func TestHandleHooks(t *testing.T) {
},
{
name: "pod, annotation, onError=continue = return nil",
phase: hookPhasePre,
phase: PhasePre,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -396,7 +396,7 @@ func TestHandleHooks(t *testing.T) {
},
{
name: "pod, spec, onError=fail = don't run other hooks",
phase: hookPhasePre,
phase: PhasePre,
groupResource: "pods",
item: velerotest.UnstructuredOrDie(`
{
@ -407,10 +407,10 @@ func TestHandleHooks(t *testing.T) {
"name": "name"
}
}`),
hooks: []resourceHook{
hooks: []ResourceHook{
{
name: "hook1",
pre: []v1.BackupResourceHook{
Name: "hook1",
Pre: []v1.BackupResourceHook{
{
Exec: &v1.ExecHook{
Container: "1a",
@ -427,8 +427,8 @@ func TestHandleHooks(t *testing.T) {
},
},
{
name: "hook2",
pre: []v1.BackupResourceHook{
Name: "hook2",
Pre: []v1.BackupResourceHook{
{
Exec: &v1.ExecHook{
Container: "2",
@ -439,8 +439,8 @@ func TestHandleHooks(t *testing.T) {
},
},
{
name: "hook3",
pre: []v1.BackupResourceHook{
Name: "hook3",
Pre: []v1.BackupResourceHook{
{
Exec: &v1.ExecHook{
Container: "3",
@ -463,8 +463,8 @@ func TestHandleHooks(t *testing.T) {
podCommandExecutor := &velerotest.MockPodCommandExecutor{}
defer podCommandExecutor.AssertExpectations(t)
h := &defaultItemHookHandler{
podCommandExecutor: podCommandExecutor,
h := &DefaultItemHookHandler{
PodCommandExecutor: podCommandExecutor,
}
if test.expectedPodHook != nil {
@ -472,16 +472,16 @@ func TestHandleHooks(t *testing.T) {
} else {
hookLoop:
for _, resourceHook := range test.hooks {
for _, hook := range resourceHook.pre {
for _, hook := range resourceHook.Pre {
hookError := test.hookErrorsByContainer[hook.Exec.Container]
podCommandExecutor.On("ExecutePodCommand", mock.Anything, test.item.UnstructuredContent(), "ns", "name", resourceHook.name, hook.Exec).Return(hookError)
podCommandExecutor.On("ExecutePodCommand", mock.Anything, test.item.UnstructuredContent(), "ns", "name", resourceHook.Name, hook.Exec).Return(hookError)
if hookError != nil && hook.Exec.OnError == v1.HookErrorModeFail {
break hookLoop
}
}
for _, hook := range resourceHook.post {
for _, hook := range resourceHook.Post {
hookError := test.hookErrorsByContainer[hook.Exec.Container]
podCommandExecutor.On("ExecutePodCommand", mock.Anything, test.item.UnstructuredContent(), "ns", "name", resourceHook.name, hook.Exec).Return(hookError)
podCommandExecutor.On("ExecutePodCommand", mock.Anything, test.item.UnstructuredContent(), "ns", "name", resourceHook.Name, hook.Exec).Return(hookError)
if hookError != nil && hook.Exec.OnError == v1.HookErrorModeFail {
break hookLoop
}
@ -490,7 +490,7 @@ func TestHandleHooks(t *testing.T) {
}
groupResource := schema.ParseGroupResource(test.groupResource)
err := h.handleHooks(velerotest.NewLogger(), groupResource, test.item, test.hooks, test.phase)
err := h.HandleHooks(velerotest.NewLogger(), groupResource, test.item, test.hooks, test.phase)
if test.expectedError != nil {
assert.EqualError(t, err, test.expectedError.Error())
@ -503,7 +503,7 @@ func TestHandleHooks(t *testing.T) {
}
func TestGetPodExecHookFromAnnotations(t *testing.T) {
phases := []hookPhase{"", hookPhasePre, hookPhasePost}
phases := []hookPhase{"", PhasePre, PhasePost}
for _, phase := range phases {
tests := []struct {
name string
@ -680,14 +680,14 @@ func TestResourceHookApplicableTo(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
h := resourceHook{
namespaces: collections.NewIncludesExcludes().Includes(test.includedNamespaces...).Excludes(test.excludedNamespaces...),
resources: collections.NewIncludesExcludes().Includes(test.includedResources...).Excludes(test.excludedResources...),
h := ResourceHook{
Namespaces: collections.NewIncludesExcludes().Includes(test.includedNamespaces...).Excludes(test.excludedNamespaces...),
Resources: collections.NewIncludesExcludes().Includes(test.includedResources...).Excludes(test.excludedResources...),
}
if test.labelSelector != "" {
selector, err := labels.Parse(test.labelSelector)
require.NoError(t, err)
h.labelSelector = selector
h.LabelSelector = selector
}
result := h.applicableTo(test.resource, test.namespace, test.labels)

View File

@ -38,6 +38,7 @@ import (
"k8s.io/apimachinery/pkg/types"
kubeerrs "k8s.io/apimachinery/pkg/util/errors"
"github.com/vmware-tanzu/velero/internal/hook"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/client"
"github.com/vmware-tanzu/velero/pkg/discovery"
@ -179,13 +180,13 @@ func getNamespaceIncludesExcludes(backup *velerov1api.Backup) *collections.Inclu
return collections.NewIncludesExcludes().Includes(backup.Spec.IncludedNamespaces...).Excludes(backup.Spec.ExcludedNamespaces...)
}
func getResourceHooks(hookSpecs []velerov1api.BackupResourceHookSpec, discoveryHelper discovery.Helper) ([]resourceHook, error) {
resourceHooks := make([]resourceHook, 0, len(hookSpecs))
func getResourceHooks(hookSpecs []velerov1api.BackupResourceHookSpec, discoveryHelper discovery.Helper) ([]hook.ResourceHook, error) {
resourceHooks := make([]hook.ResourceHook, 0, len(hookSpecs))
for _, s := range hookSpecs {
h, err := getResourceHook(s, discoveryHelper)
if err != nil {
return []resourceHook{}, err
return []hook.ResourceHook{}, err
}
resourceHooks = append(resourceHooks, h)
@ -194,21 +195,21 @@ func getResourceHooks(hookSpecs []velerov1api.BackupResourceHookSpec, discoveryH
return resourceHooks, nil
}
func getResourceHook(hookSpec velerov1api.BackupResourceHookSpec, discoveryHelper discovery.Helper) (resourceHook, error) {
h := resourceHook{
name: hookSpec.Name,
namespaces: collections.NewIncludesExcludes().Includes(hookSpec.IncludedNamespaces...).Excludes(hookSpec.ExcludedNamespaces...),
resources: getResourceIncludesExcludes(discoveryHelper, hookSpec.IncludedResources, hookSpec.ExcludedResources),
pre: hookSpec.PreHooks,
post: hookSpec.PostHooks,
func getResourceHook(hookSpec velerov1api.BackupResourceHookSpec, discoveryHelper discovery.Helper) (hook.ResourceHook, error) {
h := hook.ResourceHook{
Name: hookSpec.Name,
Namespaces: collections.NewIncludesExcludes().Includes(hookSpec.IncludedNamespaces...).Excludes(hookSpec.ExcludedNamespaces...),
Resources: getResourceIncludesExcludes(discoveryHelper, hookSpec.IncludedResources, hookSpec.ExcludedResources),
Pre: hookSpec.PreHooks,
Post: hookSpec.PostHooks,
}
if hookSpec.LabelSelector != nil {
labelSelector, err := metav1.LabelSelectorAsSelector(hookSpec.LabelSelector)
if err != nil {
return resourceHook{}, errors.WithStack(err)
return hook.ResourceHook{}, errors.WithStack(err)
}
h.labelSelector = labelSelector
h.LabelSelector = labelSelector
}
return h, nil
@ -312,8 +313,8 @@ func (kb *kubernetesBackupper) Backup(log logrus.FieldLogger, backupRequest *Req
resticBackupper: resticBackupper,
resticSnapshotTracker: newPVCSnapshotTracker(),
volumeSnapshotterGetter: volumeSnapshotterGetter,
itemHookHandler: &defaultItemHookHandler{
podCommandExecutor: kb.podCommandExecutor,
itemHookHandler: &hook.DefaultItemHookHandler{
PodCommandExecutor: kb.podCommandExecutor,
},
}

View File

@ -34,6 +34,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
kubeerrs "k8s.io/apimachinery/pkg/util/errors"
"github.com/vmware-tanzu/velero/internal/hook"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/client"
"github.com/vmware-tanzu/velero/pkg/discovery"
@ -54,7 +55,7 @@ type itemBackupper struct {
resticSnapshotTracker *pvcSnapshotTracker
volumeSnapshotterGetter VolumeSnapshotterGetter
itemHookHandler itemHookHandler
itemHookHandler hook.ItemHookHandler
snapshotLocationVolumeSnapshotters map[string]velero.VolumeSnapshotter
}
@ -120,7 +121,7 @@ func (ib *itemBackupper) backupItem(logger logrus.FieldLogger, obj runtime.Unstr
log.Info("Backing up item")
log.Debug("Executing pre hooks")
if err := ib.itemHookHandler.handleHooks(log, groupResource, obj, ib.backupRequest.ResourceHooks, hookPhasePre); err != nil {
if err := ib.itemHookHandler.HandleHooks(log, groupResource, obj, ib.backupRequest.ResourceHooks, hook.PhasePre); err != nil {
return false, err
}
@ -172,7 +173,7 @@ func (ib *itemBackupper) backupItem(logger logrus.FieldLogger, obj runtime.Unstr
// if there was an error running actions, execute post hooks and return
log.Debug("Executing post hooks")
if err := ib.itemHookHandler.handleHooks(log, groupResource, obj, ib.backupRequest.ResourceHooks, hookPhasePost); err != nil {
if err := ib.itemHookHandler.HandleHooks(log, groupResource, obj, ib.backupRequest.ResourceHooks, hook.PhasePost); err != nil {
backupErrs = append(backupErrs, err)
}
@ -202,7 +203,7 @@ func (ib *itemBackupper) backupItem(logger logrus.FieldLogger, obj runtime.Unstr
}
log.Debug("Executing post hooks")
if err := ib.itemHookHandler.handleHooks(log, groupResource, obj, ib.backupRequest.ResourceHooks, hookPhasePost); err != nil {
if err := ib.itemHookHandler.HandleHooks(log, groupResource, obj, ib.backupRequest.ResourceHooks, hook.PhasePost); err != nil {
backupErrs = append(backupErrs, err)
}

View File

@ -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.
@ -20,6 +20,7 @@ import (
"fmt"
"sort"
"github.com/vmware-tanzu/velero/internal/hook"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/util/collections"
"github.com/vmware-tanzu/velero/pkg/volume"
@ -40,7 +41,7 @@ type Request struct {
SnapshotLocations []*velerov1api.VolumeSnapshotLocation
NamespaceIncludesExcludes *collections.IncludesExcludes
ResourceIncludesExcludes *collections.IncludesExcludes
ResourceHooks []resourceHook
ResourceHooks []hook.ResourceHook
ResolvedActions []resolvedAction
VolumeSnapshots []*volume.Snapshot