Move plugin interfaces to same package (#1264)
* Move plugin interfaces to same package Signed-off-by: Carlisia <carlisiac@vmware.com>pull/1294/head
parent
7674332313
commit
73514a003b
|
@ -0,0 +1 @@
|
|||
Move all the interfaces and associated types necessary to implement all of the Velero plugins to under the new package `velero`.
|
|
@ -34,8 +34,8 @@ import (
|
|||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/client"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/discovery"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/podexec"
|
||||
"github.com/heptio/velero/pkg/restic"
|
||||
"github.com/heptio/velero/pkg/util/collections"
|
||||
|
@ -49,7 +49,7 @@ const BackupVersion = 1
|
|||
type Backupper interface {
|
||||
// Backup takes a backup using the specification in the api.Backup and writes backup and log data
|
||||
// to the given writers.
|
||||
Backup(logger logrus.FieldLogger, backup *Request, backupFile io.Writer, actions []ItemAction, blockStoreGetter BlockStoreGetter) error
|
||||
Backup(logger logrus.FieldLogger, backup *Request, backupFile io.Writer, actions []velero.BackupItemAction, blockStoreGetter BlockStoreGetter) error
|
||||
}
|
||||
|
||||
// kubernetesBackupper implements Backupper.
|
||||
|
@ -69,7 +69,7 @@ type itemKey struct {
|
|||
}
|
||||
|
||||
type resolvedAction struct {
|
||||
ItemAction
|
||||
velero.BackupItemAction
|
||||
|
||||
resourceIncludesExcludes *collections.IncludesExcludes
|
||||
namespaceIncludesExcludes *collections.IncludesExcludes
|
||||
|
@ -108,7 +108,7 @@ func NewKubernetesBackupper(
|
|||
}, nil
|
||||
}
|
||||
|
||||
func resolveActions(actions []ItemAction, helper discovery.Helper) ([]resolvedAction, error) {
|
||||
func resolveActions(actions []velero.BackupItemAction, helper discovery.Helper) ([]resolvedAction, error) {
|
||||
var resolved []resolvedAction
|
||||
|
||||
for _, action := range actions {
|
||||
|
@ -128,7 +128,7 @@ func resolveActions(actions []ItemAction, helper discovery.Helper) ([]resolvedAc
|
|||
}
|
||||
|
||||
res := resolvedAction{
|
||||
ItemAction: action,
|
||||
BackupItemAction: action,
|
||||
resourceIncludesExcludes: resources,
|
||||
namespaceIncludesExcludes: namespaces,
|
||||
selector: selector,
|
||||
|
@ -210,12 +210,12 @@ func getResourceHook(hookSpec api.BackupResourceHookSpec, discoveryHelper discov
|
|||
}
|
||||
|
||||
type BlockStoreGetter interface {
|
||||
GetBlockStore(name string) (cloudprovider.BlockStore, error)
|
||||
GetBlockStore(name string) (velero.BlockStore, error)
|
||||
}
|
||||
|
||||
// Backup backs up the items specified in the Backup, placing them in a gzip-compressed tar file
|
||||
// written to backupFile. The finalized api.Backup is written to metadata.
|
||||
func (kb *kubernetesBackupper) Backup(logger logrus.FieldLogger, backupRequest *Request, backupFile io.Writer, actions []ItemAction, blockStoreGetter BlockStoreGetter) error {
|
||||
func (kb *kubernetesBackupper) Backup(logger logrus.FieldLogger, backupRequest *Request, backupFile io.Writer, actions []velero.BackupItemAction, blockStoreGetter BlockStoreGetter) error {
|
||||
gzippedData := gzip.NewWriter(backupFile)
|
||||
defer gzippedData.Close()
|
||||
|
||||
|
|
|
@ -24,28 +24,29 @@ import (
|
|||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// backupPVAction inspects a PersistentVolumeClaim for the PersistentVolume
|
||||
// PVCAction inspects a PersistentVolumeClaim for the PersistentVolume
|
||||
// that it references and backs it up
|
||||
type backupPVAction struct {
|
||||
type PVCAction struct {
|
||||
log logrus.FieldLogger
|
||||
}
|
||||
|
||||
func NewBackupPVAction(logger logrus.FieldLogger) ItemAction {
|
||||
return &backupPVAction{log: logger}
|
||||
func NewPVCAction(logger logrus.FieldLogger) *PVCAction {
|
||||
return &PVCAction{log: logger}
|
||||
}
|
||||
|
||||
func (a *backupPVAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (a *PVCAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"persistentvolumeclaims"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Execute finds the PersistentVolume bound by the provided
|
||||
// PersistentVolumeClaim, if any, and backs it up
|
||||
func (a *backupPVAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []ResourceIdentifier, error) {
|
||||
a.log.Info("Executing backupPVAction")
|
||||
func (a *PVCAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
|
||||
a.log.Info("Executing PVCAction")
|
||||
|
||||
var pvc corev1api.PersistentVolumeClaim
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(item.UnstructuredContent(), &pvc); err != nil {
|
||||
|
@ -56,9 +57,9 @@ func (a *backupPVAction) Execute(item runtime.Unstructured, backup *v1.Backup) (
|
|||
return item, nil, nil
|
||||
}
|
||||
|
||||
pv := ResourceIdentifier{
|
||||
pv := velero.ResourceIdentifier{
|
||||
GroupResource: kuberesource.PersistentVolumes,
|
||||
Name: pvc.Spec.VolumeName,
|
||||
}
|
||||
return item, []ResourceIdentifier{pv}, nil
|
||||
return item, []velero.ResourceIdentifier{pv}, nil
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
||||
|
@ -39,7 +40,7 @@ func TestBackupPVAction(t *testing.T) {
|
|||
|
||||
backup := &v1.Backup{}
|
||||
|
||||
a := NewBackupPVAction(velerotest.NewLogger())
|
||||
a := NewPVCAction(velerotest.NewLogger())
|
||||
|
||||
// no spec.volumeName should result in no error
|
||||
// and no additional items
|
||||
|
@ -81,7 +82,7 @@ func TestBackupPVAction(t *testing.T) {
|
|||
_, additional, err = a.Execute(pvc, backup)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, additional, 1)
|
||||
assert.Equal(t, ResourceIdentifier{GroupResource: kuberesource.PersistentVolumes, Name: "myVolume"}, additional[0])
|
||||
assert.Equal(t, velero.ResourceIdentifier{GroupResource: kuberesource.PersistentVolumes, Name: "myVolume"}, additional[0])
|
||||
|
||||
// empty spec.volumeName when status.phase is 'Bound' should
|
||||
// result in no error and no additional items
|
||||
|
|
|
@ -38,6 +38,7 @@ import (
|
|||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/client"
|
||||
"github.com/heptio/velero/pkg/discovery"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/podexec"
|
||||
"github.com/heptio/velero/pkg/restic"
|
||||
"github.com/heptio/velero/pkg/util/collections"
|
||||
|
@ -54,19 +55,19 @@ var (
|
|||
)
|
||||
|
||||
type fakeAction struct {
|
||||
selector ResourceSelector
|
||||
selector velero.ResourceSelector
|
||||
ids []string
|
||||
backups []v1.Backup
|
||||
additionalItems []ResourceIdentifier
|
||||
additionalItems []velero.ResourceIdentifier
|
||||
}
|
||||
|
||||
var _ ItemAction = &fakeAction{}
|
||||
var _ velero.BackupItemAction = &fakeAction{}
|
||||
|
||||
func newFakeAction(resource string) *fakeAction {
|
||||
return (&fakeAction{}).ForResource(resource)
|
||||
}
|
||||
|
||||
func (a *fakeAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []ResourceIdentifier, error) {
|
||||
func (a *fakeAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
|
||||
metadata, err := meta.Accessor(item)
|
||||
if err != nil {
|
||||
return item, a.additionalItems, err
|
||||
|
@ -77,7 +78,7 @@ func (a *fakeAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runt
|
|||
return item, a.additionalItems, nil
|
||||
}
|
||||
|
||||
func (a *fakeAction) AppliesTo() (ResourceSelector, error) {
|
||||
func (a *fakeAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return a.selector, nil
|
||||
}
|
||||
|
||||
|
@ -89,34 +90,34 @@ func (a *fakeAction) ForResource(resource string) *fakeAction {
|
|||
func TestResolveActions(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []ItemAction
|
||||
input []velero.BackupItemAction
|
||||
expected []resolvedAction
|
||||
resourcesWithErrors []string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "empty input",
|
||||
input: []ItemAction{},
|
||||
input: []velero.BackupItemAction{},
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
name: "resolve error",
|
||||
input: []ItemAction{&fakeAction{selector: ResourceSelector{LabelSelector: "=invalid-selector"}}},
|
||||
input: []velero.BackupItemAction{&fakeAction{selector: velero.ResourceSelector{LabelSelector: "=invalid-selector"}}},
|
||||
expected: nil,
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "resolved",
|
||||
input: []ItemAction{newFakeAction("foo"), newFakeAction("bar")},
|
||||
input: []velero.BackupItemAction{newFakeAction("foo"), newFakeAction("bar")},
|
||||
expected: []resolvedAction{
|
||||
{
|
||||
ItemAction: newFakeAction("foo"),
|
||||
BackupItemAction: newFakeAction("foo"),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes().Includes("foodies.somegroup"),
|
||||
namespaceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
selector: labels.Everything(),
|
||||
},
|
||||
{
|
||||
ItemAction: newFakeAction("bar"),
|
||||
BackupItemAction: newFakeAction("bar"),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes().Includes("barnacles.anothergroup"),
|
||||
namespaceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
selector: labels.Everything(),
|
||||
|
|
|
@ -34,9 +34,9 @@ import (
|
|||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/client"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/discovery"
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/podexec"
|
||||
"github.com/heptio/velero/pkg/restic"
|
||||
"github.com/heptio/velero/pkg/volume"
|
||||
|
@ -106,7 +106,7 @@ type defaultItemBackupper struct {
|
|||
|
||||
itemHookHandler itemHookHandler
|
||||
additionalItemBackupper ItemBackupper
|
||||
snapshotLocationBlockStores map[string]cloudprovider.BlockStore
|
||||
snapshotLocationBlockStores map[string]velero.BlockStore
|
||||
}
|
||||
|
||||
// backupItem backs up an individual item to tarWriter. The item may be excluded based on the
|
||||
|
@ -345,7 +345,7 @@ func (ib *defaultItemBackupper) executeActions(
|
|||
|
||||
// blockStore instantiates and initializes a BlockStore given a VolumeSnapshotLocation,
|
||||
// or returns an existing one if one's already been initialized for the location.
|
||||
func (ib *defaultItemBackupper) blockStore(snapshotLocation *api.VolumeSnapshotLocation) (cloudprovider.BlockStore, error) {
|
||||
func (ib *defaultItemBackupper) blockStore(snapshotLocation *api.VolumeSnapshotLocation) (velero.BlockStore, error) {
|
||||
if bs, ok := ib.snapshotLocationBlockStores[snapshotLocation.Name]; ok {
|
||||
return bs, nil
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ func (ib *defaultItemBackupper) blockStore(snapshotLocation *api.VolumeSnapshotL
|
|||
}
|
||||
|
||||
if ib.snapshotLocationBlockStores == nil {
|
||||
ib.snapshotLocationBlockStores = make(map[string]cloudprovider.BlockStore)
|
||||
ib.snapshotLocationBlockStores = make(map[string]velero.BlockStore)
|
||||
}
|
||||
ib.snapshotLocationBlockStores[snapshotLocation.Name] = bs
|
||||
|
||||
|
@ -405,7 +405,7 @@ func (ib *defaultItemBackupper) takePVSnapshot(obj runtime.Unstructured, log log
|
|||
|
||||
var (
|
||||
volumeID, location string
|
||||
blockStore cloudprovider.BlockStore
|
||||
blockStore velero.BlockStore
|
||||
)
|
||||
|
||||
for _, snapshotLocation := range ib.backupRequest.SnapshotLocations {
|
||||
|
|
|
@ -39,7 +39,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
resticmocks "github.com/heptio/velero/pkg/restic/mocks"
|
||||
"github.com/heptio/velero/pkg/util/collections"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
|
@ -166,7 +166,7 @@ func TestBackupItemNoSkips(t *testing.T) {
|
|||
tarHeaderWriteError bool
|
||||
customAction bool
|
||||
expectedActionID string
|
||||
customActionAdditionalItemIdentifiers []ResourceIdentifier
|
||||
customActionAdditionalItemIdentifiers []velero.ResourceIdentifier
|
||||
customActionAdditionalItems []runtime.Unstructured
|
||||
groupResource string
|
||||
snapshottableVolumes map[string]v1.VolumeBackupInfo
|
||||
|
@ -239,7 +239,7 @@ func TestBackupItemNoSkips(t *testing.T) {
|
|||
expectedTarHeaderName: "resources/resource.group/namespaces/myns/bar.json",
|
||||
customAction: true,
|
||||
expectedActionID: "myns/bar",
|
||||
customActionAdditionalItemIdentifiers: []ResourceIdentifier{
|
||||
customActionAdditionalItemIdentifiers: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: schema.GroupResource{Group: "g1", Resource: "r1"},
|
||||
Namespace: "ns1",
|
||||
|
@ -265,7 +265,7 @@ func TestBackupItemNoSkips(t *testing.T) {
|
|||
expectedTarHeaderName: "resources/resource.group/namespaces/myns/bar.json",
|
||||
customAction: true,
|
||||
expectedActionID: "myns/bar",
|
||||
customActionAdditionalItemIdentifiers: []ResourceIdentifier{
|
||||
customActionAdditionalItemIdentifiers: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: schema.GroupResource{Group: "g1", Resource: "r1"},
|
||||
Namespace: "ns1",
|
||||
|
@ -397,7 +397,7 @@ func TestBackupItemNoSkips(t *testing.T) {
|
|||
}
|
||||
backup.ResolvedActions = []resolvedAction{
|
||||
{
|
||||
ItemAction: action,
|
||||
BackupItemAction: action,
|
||||
namespaceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes().Includes(groupResource.String()),
|
||||
selector: labels.Everything(),
|
||||
|
@ -548,10 +548,10 @@ func TestBackupItemNoSkips(t *testing.T) {
|
|||
}
|
||||
|
||||
type blockStoreGetter struct {
|
||||
blockStore cloudprovider.BlockStore
|
||||
blockStore velero.BlockStore
|
||||
}
|
||||
|
||||
func (b *blockStoreGetter) GetBlockStore(name string) (cloudprovider.BlockStore, error) {
|
||||
func (b *blockStoreGetter) GetBlockStore(name string) (velero.BlockStore, error) {
|
||||
if b.blockStore != nil {
|
||||
return b.blockStore, nil
|
||||
}
|
||||
|
@ -560,7 +560,7 @@ func (b *blockStoreGetter) GetBlockStore(name string) (cloudprovider.BlockStore,
|
|||
|
||||
type addAnnotationAction struct{}
|
||||
|
||||
func (a *addAnnotationAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []ResourceIdentifier, error) {
|
||||
func (a *addAnnotationAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
|
||||
// since item actions run out-of-proc, do a deep-copy here to simulate passing data
|
||||
// across a process boundary.
|
||||
copy := item.(*unstructured.Unstructured).DeepCopy()
|
||||
|
@ -580,7 +580,7 @@ func (a *addAnnotationAction) Execute(item runtime.Unstructured, backup *v1.Back
|
|||
return copy, nil, nil
|
||||
}
|
||||
|
||||
func (a *addAnnotationAction) AppliesTo() (ResourceSelector, error) {
|
||||
func (a *addAnnotationAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
|
@ -600,7 +600,7 @@ func TestItemActionModificationsToItemPersist(t *testing.T) {
|
|||
ResourceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
ResolvedActions: []resolvedAction{
|
||||
{
|
||||
ItemAction: &addAnnotationAction{},
|
||||
BackupItemAction: &addAnnotationAction{},
|
||||
namespaceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
selector: labels.Everything(),
|
||||
|
@ -656,7 +656,7 @@ func TestResticAnnotationsPersist(t *testing.T) {
|
|||
ResourceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
ResolvedActions: []resolvedAction{
|
||||
{
|
||||
ItemAction: &addAnnotationAction{},
|
||||
BackupItemAction: &addAnnotationAction{},
|
||||
namespaceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
selector: labels.Everything(),
|
||||
|
|
|
@ -16,10 +16,13 @@ limitations under the License.
|
|||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
package mocks
|
||||
|
||||
import backup "github.com/heptio/velero/pkg/backup"
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
import runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
import v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// ItemAction is an autogenerated mock type for the ItemAction type
|
||||
type ItemAction struct {
|
||||
|
@ -27,14 +30,14 @@ type ItemAction struct {
|
|||
}
|
||||
|
||||
// AppliesTo provides a mock function with given fields:
|
||||
func (_m *ItemAction) AppliesTo() (backup.ResourceSelector, error) {
|
||||
func (_m *ItemAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 backup.ResourceSelector
|
||||
if rf, ok := ret.Get(0).(func() backup.ResourceSelector); ok {
|
||||
var r0 velero.ResourceSelector
|
||||
if rf, ok := ret.Get(0).(func() velero.ResourceSelector); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(backup.ResourceSelector)
|
||||
r0 = ret.Get(0).(velero.ResourceSelector)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
|
@ -48,7 +51,7 @@ func (_m *ItemAction) AppliesTo() (backup.ResourceSelector, error) {
|
|||
}
|
||||
|
||||
// Execute provides a mock function with given fields: item, _a1
|
||||
func (_m *ItemAction) Execute(item runtime.Unstructured, _a1 *v1.Backup) (runtime.Unstructured, []backup.ResourceIdentifier, error) {
|
||||
func (_m *ItemAction) Execute(item runtime.Unstructured, _a1 *v1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
|
||||
ret := _m.Called(item, _a1)
|
||||
|
||||
var r0 runtime.Unstructured
|
||||
|
@ -60,12 +63,12 @@ func (_m *ItemAction) Execute(item runtime.Unstructured, _a1 *v1.Backup) (runtim
|
|||
}
|
||||
}
|
||||
|
||||
var r1 []backup.ResourceIdentifier
|
||||
if rf, ok := ret.Get(1).(func(runtime.Unstructured, *v1.Backup) []backup.ResourceIdentifier); ok {
|
||||
var r1 []velero.ResourceIdentifier
|
||||
if rf, ok := ret.Get(1).(func(runtime.Unstructured, *v1.Backup) []velero.ResourceIdentifier); ok {
|
||||
r1 = rf(item, _a1)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).([]backup.ResourceIdentifier)
|
||||
r1 = ret.Get(1).([]velero.ResourceIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,21 +24,22 @@ import (
|
|||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// podAction implements ItemAction.
|
||||
type podAction struct {
|
||||
// PodAction implements ItemAction.
|
||||
type PodAction struct {
|
||||
log logrus.FieldLogger
|
||||
}
|
||||
|
||||
// NewPodAction creates a new ItemAction for pods.
|
||||
func NewPodAction(logger logrus.FieldLogger) ItemAction {
|
||||
return &podAction{log: logger}
|
||||
func NewPodAction(logger logrus.FieldLogger) *PodAction {
|
||||
return &PodAction{log: logger}
|
||||
}
|
||||
|
||||
// AppliesTo returns a ResourceSelector that applies only to pods.
|
||||
func (a *podAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (a *PodAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"pods"},
|
||||
}, nil
|
||||
}
|
||||
|
@ -46,7 +47,7 @@ func (a *podAction) AppliesTo() (ResourceSelector, error) {
|
|||
// Execute scans the pod's spec.volumes for persistentVolumeClaim volumes and returns a
|
||||
// ResourceIdentifier list containing references to all of the persistentVolumeClaim volumes used by
|
||||
// the pod. This ensures that when a pod is backed up, all referenced PVCs are backed up too.
|
||||
func (a *podAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []ResourceIdentifier, error) {
|
||||
func (a *PodAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
|
||||
a.log.Info("Executing podAction")
|
||||
defer a.log.Info("Done executing podAction")
|
||||
|
||||
|
@ -60,12 +61,12 @@ func (a *podAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runti
|
|||
return item, nil, nil
|
||||
}
|
||||
|
||||
var additionalItems []ResourceIdentifier
|
||||
var additionalItems []velero.ResourceIdentifier
|
||||
for _, volume := range pod.Spec.Volumes {
|
||||
if volume.PersistentVolumeClaim != nil && volume.PersistentVolumeClaim.ClaimName != "" {
|
||||
a.log.Infof("Adding pvc %s to additionalItems", volume.PersistentVolumeClaim.ClaimName)
|
||||
|
||||
additionalItems = append(additionalItems, ResourceIdentifier{
|
||||
additionalItems = append(additionalItems, velero.ResourceIdentifier{
|
||||
GroupResource: kuberesource.PersistentVolumeClaims,
|
||||
Namespace: pod.Namespace,
|
||||
Name: volume.PersistentVolumeClaim.ClaimName,
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
||||
|
@ -33,7 +34,7 @@ func TestPodActionAppliesTo(t *testing.T) {
|
|||
actual, err := a.AppliesTo()
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := ResourceSelector{
|
||||
expected := velero.ResourceSelector{
|
||||
IncludedResources: []string{"pods"},
|
||||
}
|
||||
assert.Equal(t, expected, actual)
|
||||
|
@ -43,7 +44,7 @@ func TestPodActionExecute(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
pod runtime.Unstructured
|
||||
expected []ResourceIdentifier
|
||||
expected []velero.ResourceIdentifier
|
||||
}{
|
||||
{
|
||||
name: "no spec.volumes",
|
||||
|
@ -109,7 +110,7 @@ func TestPodActionExecute(t *testing.T) {
|
|||
}
|
||||
}
|
||||
`),
|
||||
expected: []ResourceIdentifier{
|
||||
expected: []velero.ResourceIdentifier{
|
||||
{GroupResource: kuberesource.PersistentVolumeClaims, Namespace: "foo", Name: "claim1"},
|
||||
{GroupResource: kuberesource.PersistentVolumeClaims, Namespace: "foo", Name: "claim2"},
|
||||
},
|
||||
|
|
|
@ -228,7 +228,7 @@ func TestBackupResource(t *testing.T) {
|
|||
},
|
||||
ResolvedActions: []resolvedAction{
|
||||
{
|
||||
ItemAction: newFakeAction("pods"),
|
||||
BackupItemAction: newFakeAction("pods"),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes().Includes("pods"),
|
||||
},
|
||||
},
|
||||
|
@ -390,7 +390,7 @@ func TestBackupResourceCohabitation(t *testing.T) {
|
|||
ResourceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
|
||||
ResolvedActions: []resolvedAction{
|
||||
{
|
||||
ItemAction: newFakeAction("pods"),
|
||||
BackupItemAction: newFakeAction("pods"),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes().Includes("pods"),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -28,16 +28,17 @@ import (
|
|||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
velerodiscovery "github.com/heptio/velero/pkg/discovery"
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// serviceAccountAction implements ItemAction.
|
||||
type serviceAccountAction struct {
|
||||
// ServiceAccountAction implements ItemAction.
|
||||
type ServiceAccountAction struct {
|
||||
log logrus.FieldLogger
|
||||
clusterRoleBindings []ClusterRoleBinding
|
||||
}
|
||||
|
||||
// NewServiceAccountAction creates a new ItemAction for service accounts.
|
||||
func NewServiceAccountAction(logger logrus.FieldLogger, clusterRoleBindingListers map[string]ClusterRoleBindingLister, discoveryHelper velerodiscovery.Helper) (ItemAction, error) {
|
||||
func NewServiceAccountAction(logger logrus.FieldLogger, clusterRoleBindingListers map[string]ClusterRoleBindingLister, discoveryHelper velerodiscovery.Helper) (*ServiceAccountAction, error) {
|
||||
// Look up the supported RBAC version
|
||||
var supportedAPI metav1.GroupVersionForDiscovery
|
||||
for _, ag := range discoveryHelper.APIGroups() {
|
||||
|
@ -56,15 +57,15 @@ func NewServiceAccountAction(logger logrus.FieldLogger, clusterRoleBindingLister
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &serviceAccountAction{
|
||||
return &ServiceAccountAction{
|
||||
log: logger,
|
||||
clusterRoleBindings: crbs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AppliesTo returns a ResourceSelector that applies only to service accounts.
|
||||
func (a *serviceAccountAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (a *ServiceAccountAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"serviceaccounts"},
|
||||
}, nil
|
||||
}
|
||||
|
@ -72,9 +73,9 @@ func (a *serviceAccountAction) AppliesTo() (ResourceSelector, error) {
|
|||
// Execute checks for any ClusterRoleBindings that have this service account as a subject, and
|
||||
// adds the ClusterRoleBinding and associated ClusterRole to the list of additional items to
|
||||
// be backed up.
|
||||
func (a *serviceAccountAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []ResourceIdentifier, error) {
|
||||
a.log.Info("Running serviceAccountAction")
|
||||
defer a.log.Info("Done running serviceAccountAction")
|
||||
func (a *ServiceAccountAction) Execute(item runtime.Unstructured, backup *v1.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
|
||||
a.log.Info("Running ServiceAccountAction")
|
||||
defer a.log.Info("Done running ServiceAccountAction")
|
||||
|
||||
objectMeta, err := meta.Accessor(item)
|
||||
if err != nil {
|
||||
|
@ -101,16 +102,16 @@ func (a *serviceAccountAction) Execute(item runtime.Unstructured, backup *v1.Bac
|
|||
}
|
||||
}
|
||||
|
||||
var additionalItems []ResourceIdentifier
|
||||
var additionalItems []velero.ResourceIdentifier
|
||||
for binding := range bindings {
|
||||
additionalItems = append(additionalItems, ResourceIdentifier{
|
||||
additionalItems = append(additionalItems, velero.ResourceIdentifier{
|
||||
GroupResource: kuberesource.ClusterRoleBindings,
|
||||
Name: binding,
|
||||
})
|
||||
}
|
||||
|
||||
for role := range roles {
|
||||
additionalItems = append(additionalItems, ResourceIdentifier{
|
||||
additionalItems = append(additionalItems, velero.ResourceIdentifier{
|
||||
GroupResource: kuberesource.ClusterRoles,
|
||||
Name: role,
|
||||
})
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
||||
|
@ -77,12 +78,12 @@ func (f FakeV1beta1ClusterRoleBindingLister) List() ([]ClusterRoleBinding, error
|
|||
func TestServiceAccountActionAppliesTo(t *testing.T) {
|
||||
// Instantiating the struct directly since using
|
||||
// NewServiceAccountAction requires a full kubernetes clientset
|
||||
a := &serviceAccountAction{}
|
||||
a := &ServiceAccountAction{}
|
||||
|
||||
actual, err := a.AppliesTo()
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := ResourceSelector{
|
||||
expected := velero.ResourceSelector{
|
||||
IncludedResources: []string{"serviceaccounts"},
|
||||
}
|
||||
assert.Equal(t, expected, actual)
|
||||
|
@ -189,9 +190,7 @@ func TestNewServiceAccountAction(t *testing.T) {
|
|||
}
|
||||
action, err := NewServiceAccountAction(logger, clusterRoleBindingListers, &discoveryHelper)
|
||||
require.NoError(t, err)
|
||||
saAction, ok := action.(*serviceAccountAction)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, test.expectedCRBs, saAction.clusterRoleBindings)
|
||||
assert.Equal(t, test.expectedCRBs, action.clusterRoleBindings)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +200,7 @@ func TestServiceAccountActionExecute(t *testing.T) {
|
|||
name string
|
||||
serviceAccount runtime.Unstructured
|
||||
crbs []rbac.ClusterRoleBinding
|
||||
expectedAdditionalItems []ResourceIdentifier
|
||||
expectedAdditionalItems []velero.ResourceIdentifier
|
||||
}{
|
||||
{
|
||||
name: "no crbs",
|
||||
|
@ -345,7 +344,7 @@ func TestServiceAccountActionExecute(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
expectedAdditionalItems: []ResourceIdentifier{
|
||||
expectedAdditionalItems: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.ClusterRoleBindings,
|
||||
Name: "crb-2",
|
||||
|
@ -377,7 +376,7 @@ func TestServiceAccountActionExecute(t *testing.T) {
|
|||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// Create the action struct directly so we don't need to mock a clientset
|
||||
action := &serviceAccountAction{
|
||||
action := &ServiceAccountAction{
|
||||
log: velerotest.NewLogger(),
|
||||
clusterRoleBindings: newV1ClusterRoleBindingList(test.crbs),
|
||||
}
|
||||
|
@ -409,7 +408,7 @@ func TestServiceAccountActionExecuteOnBeta1(t *testing.T) {
|
|||
name string
|
||||
serviceAccount runtime.Unstructured
|
||||
crbs []rbacbeta.ClusterRoleBinding
|
||||
expectedAdditionalItems []ResourceIdentifier
|
||||
expectedAdditionalItems []velero.ResourceIdentifier
|
||||
}{
|
||||
{
|
||||
name: "no crbs",
|
||||
|
@ -553,7 +552,7 @@ func TestServiceAccountActionExecuteOnBeta1(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
expectedAdditionalItems: []ResourceIdentifier{
|
||||
expectedAdditionalItems: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: kuberesource.ClusterRoleBindings,
|
||||
Name: "crb-2",
|
||||
|
@ -585,7 +584,7 @@ func TestServiceAccountActionExecuteOnBeta1(t *testing.T) {
|
|||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// Create the action struct directly so we don't need to mock a clientset
|
||||
action := &serviceAccountAction{
|
||||
action := &ServiceAccountAction{
|
||||
log: velerotest.NewLogger(),
|
||||
clusterRoleBindings: newV1beta1ClusterRoleBindingList(test.crbs),
|
||||
}
|
||||
|
|
|
@ -32,8 +32,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
const regionKey = "region"
|
||||
|
@ -43,7 +41,7 @@ const regionKey = "region"
|
|||
// from snapshot.
|
||||
var iopsVolumeTypes = sets.NewString("io1")
|
||||
|
||||
type blockStore struct {
|
||||
type BlockStore struct {
|
||||
log logrus.FieldLogger
|
||||
ec2 *ec2.EC2
|
||||
}
|
||||
|
@ -61,11 +59,11 @@ func getSession(config *aws.Config) (*session.Session, error) {
|
|||
return sess, nil
|
||||
}
|
||||
|
||||
func NewBlockStore(logger logrus.FieldLogger) cloudprovider.BlockStore {
|
||||
return &blockStore{log: logger}
|
||||
func NewBlockStore(logger logrus.FieldLogger) *BlockStore {
|
||||
return &BlockStore{log: logger}
|
||||
}
|
||||
|
||||
func (b *blockStore) Init(config map[string]string) error {
|
||||
func (b *BlockStore) Init(config map[string]string) error {
|
||||
region := config[regionKey]
|
||||
if region == "" {
|
||||
return errors.Errorf("missing %s in aws configuration", regionKey)
|
||||
|
@ -83,7 +81,7 @@ func (b *blockStore) Init(config map[string]string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *blockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (volumeID string, err error) {
|
||||
func (b *BlockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (volumeID string, err error) {
|
||||
// describe the snapshot so we can apply its tags to the volume
|
||||
snapReq := &ec2.DescribeSnapshotsInput{
|
||||
SnapshotIds: []*string{&snapshotID},
|
||||
|
@ -124,7 +122,7 @@ func (b *blockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ s
|
|||
return *res.VolumeId, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
||||
func (b *BlockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
||||
volumeInfo, err := b.describeVolume(volumeID)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
|
@ -146,7 +144,7 @@ func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, e
|
|||
return volumeType, iops, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) describeVolume(volumeID string) (*ec2.Volume, error) {
|
||||
func (b *BlockStore) describeVolume(volumeID string) (*ec2.Volume, error) {
|
||||
req := &ec2.DescribeVolumesInput{
|
||||
VolumeIds: []*string{&volumeID},
|
||||
}
|
||||
|
@ -162,7 +160,7 @@ func (b *blockStore) describeVolume(volumeID string) (*ec2.Volume, error) {
|
|||
return res.Volumes[0], nil
|
||||
}
|
||||
|
||||
func (b *blockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||
func (b *BlockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||
// describe the volume so we can copy its tags to the snapshot
|
||||
volumeInfo, err := b.describeVolume(volumeID)
|
||||
if err != nil {
|
||||
|
@ -234,7 +232,7 @@ func ec2Tag(key, val string) *ec2.Tag {
|
|||
return &ec2.Tag{Key: &key, Value: &val}
|
||||
}
|
||||
|
||||
func (b *blockStore) DeleteSnapshot(snapshotID string) error {
|
||||
func (b *BlockStore) DeleteSnapshot(snapshotID string) error {
|
||||
req := &ec2.DeleteSnapshotInput{
|
||||
SnapshotId: &snapshotID,
|
||||
}
|
||||
|
@ -256,7 +254,7 @@ func (b *blockStore) DeleteSnapshot(snapshotID string) error {
|
|||
|
||||
var ebsVolumeIDRegex = regexp.MustCompile("vol-.*")
|
||||
|
||||
func (b *blockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, error) {
|
||||
func (b *BlockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, error) {
|
||||
pv := new(v1.PersistentVolume)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.UnstructuredContent(), pv); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
|
@ -273,7 +271,7 @@ func (b *blockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, e
|
|||
return ebsVolumeIDRegex.FindString(pv.Spec.AWSElasticBlockStore.VolumeID), nil
|
||||
}
|
||||
|
||||
func (b *blockStore) SetVolumeID(unstructuredPV runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
||||
func (b *BlockStore) SetVolumeID(unstructuredPV runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
||||
pv := new(v1.PersistentVolume)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.UnstructuredContent(), pv); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
)
|
||||
|
||||
func TestGetVolumeID(t *testing.T) {
|
||||
b := &blockStore{}
|
||||
b := &BlockStore{}
|
||||
|
||||
pv := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
|
@ -70,7 +70,7 @@ func TestGetVolumeID(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetVolumeID(t *testing.T) {
|
||||
b := &blockStore{}
|
||||
b := &BlockStore{}
|
||||
|
||||
pv := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
|
@ -105,7 +105,7 @@ func TestSetVolumeID(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetVolumeIDNoZone(t *testing.T) {
|
||||
b := &blockStore{}
|
||||
b := &BlockStore{}
|
||||
|
||||
pv := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
|
|
|
@ -24,13 +24,11 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/endpoints"
|
||||
"github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -42,7 +40,7 @@ const (
|
|||
signatureVersionKey = "signatureVersion"
|
||||
)
|
||||
|
||||
type objectStore struct {
|
||||
type ObjectStore struct {
|
||||
log logrus.FieldLogger
|
||||
s3 *s3.S3
|
||||
preSignS3 *s3.S3
|
||||
|
@ -51,8 +49,8 @@ type objectStore struct {
|
|||
signatureVersion string
|
||||
}
|
||||
|
||||
func NewObjectStore(logger logrus.FieldLogger) cloudprovider.ObjectStore {
|
||||
return &objectStore{log: logger}
|
||||
func NewObjectStore(logger logrus.FieldLogger) *ObjectStore {
|
||||
return &ObjectStore{log: logger}
|
||||
}
|
||||
|
||||
func isValidSignatureVersion(signatureVersion string) bool {
|
||||
|
@ -63,7 +61,7 @@ func isValidSignatureVersion(signatureVersion string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (o *objectStore) Init(config map[string]string) error {
|
||||
func (o *ObjectStore) Init(config map[string]string) error {
|
||||
var (
|
||||
region = config[regionKey]
|
||||
s3URL = config[s3URLKey]
|
||||
|
@ -162,7 +160,7 @@ func newAWSConfig(url, region string, forcePathStyle bool) (*aws.Config, error)
|
|||
return awsConfig, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) PutObject(bucket, key string, body io.Reader) error {
|
||||
func (o *ObjectStore) PutObject(bucket, key string, body io.Reader) error {
|
||||
req := &s3manager.UploadInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
|
@ -180,7 +178,7 @@ func (o *objectStore) PutObject(bucket, key string, body io.Reader) error {
|
|||
return errors.Wrapf(err, "error putting object %s", key)
|
||||
}
|
||||
|
||||
func (o *objectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
||||
func (o *ObjectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
||||
req := &s3.GetObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
|
@ -194,7 +192,7 @@ func (o *objectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
|||
return res.Body, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]string, error) {
|
||||
func (o *ObjectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]string, error) {
|
||||
req := &s3.ListObjectsV2Input{
|
||||
Bucket: &bucket,
|
||||
Prefix: &prefix,
|
||||
|
@ -215,7 +213,7 @@ func (o *objectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]st
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
||||
func (o *ObjectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
||||
req := &s3.ListObjectsV2Input{
|
||||
Bucket: &bucket,
|
||||
Prefix: &prefix,
|
||||
|
@ -241,7 +239,7 @@ func (o *objectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) DeleteObject(bucket, key string) error {
|
||||
func (o *ObjectStore) DeleteObject(bucket, key string) error {
|
||||
req := &s3.DeleteObjectInput{
|
||||
Bucket: &bucket,
|
||||
Key: &key,
|
||||
|
@ -252,7 +250,7 @@ func (o *objectStore) DeleteObject(bucket, key string) error {
|
|||
return errors.Wrapf(err, "error deleting object %s", key)
|
||||
}
|
||||
|
||||
func (o *objectStore) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) {
|
||||
func (o *ObjectStore) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) {
|
||||
req, _ := o.preSignS3.GetObjectRequest(&s3.GetObjectInput{
|
||||
Bucket: aws.String(bucket),
|
||||
Key: aws.String(key),
|
||||
|
|
|
@ -34,8 +34,6 @@ import (
|
|||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -47,7 +45,7 @@ const (
|
|||
disksResource = "disks"
|
||||
)
|
||||
|
||||
type blockStore struct {
|
||||
type BlockStore struct {
|
||||
log logrus.FieldLogger
|
||||
disks *disk.DisksClient
|
||||
snaps *disk.SnapshotsClient
|
||||
|
@ -67,11 +65,11 @@ func (si *snapshotIdentifier) String() string {
|
|||
return getComputeResourceName(si.subscription, si.resourceGroup, snapshotsResource, si.name)
|
||||
}
|
||||
|
||||
func NewBlockStore(logger logrus.FieldLogger) cloudprovider.BlockStore {
|
||||
return &blockStore{log: logger}
|
||||
func NewBlockStore(logger logrus.FieldLogger) *BlockStore {
|
||||
return &BlockStore{log: logger}
|
||||
}
|
||||
|
||||
func (b *blockStore) Init(config map[string]string) error {
|
||||
func (b *BlockStore) Init(config map[string]string) error {
|
||||
// 1. we need AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_RESOURCE_GROUP
|
||||
envVars, err := getRequiredValues(os.Getenv, tenantIDEnvVar, clientIDEnvVar, clientSecretEnvVar, subscriptionIDEnvVar, resourceGroupEnvVar)
|
||||
if err != nil {
|
||||
|
@ -124,7 +122,7 @@ func (b *blockStore) Init(config map[string]string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *blockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (string, error) {
|
||||
func (b *BlockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (string, error) {
|
||||
snapshotIdentifier, err := b.parseSnapshotName(snapshotID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -170,7 +168,7 @@ func (b *blockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ s
|
|||
return diskName, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
||||
func (b *BlockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
||||
res, err := b.disks.Get(context.TODO(), b.disksResourceGroup, volumeID)
|
||||
if err != nil {
|
||||
return "", nil, errors.WithStack(err)
|
||||
|
@ -183,7 +181,7 @@ func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, e
|
|||
return string(res.Sku.Name), nil, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||
func (b *BlockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||
// Lookup disk info for its Location
|
||||
diskInfo, err := b.disks.Get(context.TODO(), b.disksResourceGroup, volumeID)
|
||||
if err != nil {
|
||||
|
@ -261,7 +259,7 @@ func stringPtr(s string) *string {
|
|||
return &s
|
||||
}
|
||||
|
||||
func (b *blockStore) DeleteSnapshot(snapshotID string) error {
|
||||
func (b *BlockStore) DeleteSnapshot(snapshotID string) error {
|
||||
snapshotInfo, err := b.parseSnapshotName(snapshotID)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -309,7 +307,7 @@ var snapshotURIRegexp = regexp.MustCompile(
|
|||
//
|
||||
// TODO(1.0) remove this function and replace usage with `parseFullSnapshotName` since
|
||||
// we won't support the legacy snapshot name format for 1.0.
|
||||
func (b *blockStore) parseSnapshotName(name string) (*snapshotIdentifier, error) {
|
||||
func (b *BlockStore) parseSnapshotName(name string) (*snapshotIdentifier, error) {
|
||||
switch {
|
||||
// legacy format - name only (not fully-qualified)
|
||||
case !strings.Contains(name, "/"):
|
||||
|
@ -359,7 +357,7 @@ func parseFullSnapshotName(name string) (*snapshotIdentifier, error) {
|
|||
return snapshotID, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, error) {
|
||||
func (b *BlockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, error) {
|
||||
pv := new(v1.PersistentVolume)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.UnstructuredContent(), pv); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
|
@ -376,7 +374,7 @@ func (b *blockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, e
|
|||
return pv.Spec.AzureDisk.DiskName, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) SetVolumeID(unstructuredPV runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
||||
func (b *BlockStore) SetVolumeID(unstructuredPV runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
||||
pv := new(v1.PersistentVolume)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.UnstructuredContent(), pv); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
)
|
||||
|
||||
func TestGetVolumeID(t *testing.T) {
|
||||
b := &blockStore{}
|
||||
b := &BlockStore{}
|
||||
|
||||
pv := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
|
@ -55,7 +55,7 @@ func TestGetVolumeID(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetVolumeID(t *testing.T) {
|
||||
b := &blockStore{
|
||||
b := &BlockStore{
|
||||
disksResourceGroup: "rg",
|
||||
subscription: "sub",
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ func TestSetVolumeID(t *testing.T) {
|
|||
// the `parseFullSnapshotName` function, and remove case for legacy
|
||||
// format
|
||||
func TestParseSnapshotName(t *testing.T) {
|
||||
b := &blockStore{
|
||||
b := &BlockStore{
|
||||
subscription: "default-sub",
|
||||
disksResourceGroup: "default-rg-legacy",
|
||||
}
|
||||
|
|
|
@ -29,21 +29,19 @@ import (
|
|||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
const (
|
||||
storageAccountConfigKey = "storageAccount"
|
||||
)
|
||||
|
||||
type objectStore struct {
|
||||
type ObjectStore struct {
|
||||
blobClient *storage.BlobStorageClient
|
||||
log logrus.FieldLogger
|
||||
}
|
||||
|
||||
func NewObjectStore(logger logrus.FieldLogger) cloudprovider.ObjectStore {
|
||||
return &objectStore{log: logger}
|
||||
func NewObjectStore(logger logrus.FieldLogger) *ObjectStore {
|
||||
return &ObjectStore{log: logger}
|
||||
}
|
||||
|
||||
func getStorageAccountKey(config map[string]string) (string, error) {
|
||||
|
@ -100,7 +98,7 @@ func mapLookup(data map[string]string) func(string) string {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *objectStore) Init(config map[string]string) error {
|
||||
func (o *ObjectStore) Init(config map[string]string) error {
|
||||
storageAccountKey, err := getStorageAccountKey(config)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -118,7 +116,7 @@ func (o *objectStore) Init(config map[string]string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *objectStore) PutObject(bucket, key string, body io.Reader) error {
|
||||
func (o *ObjectStore) PutObject(bucket, key string, body io.Reader) error {
|
||||
container, err := getContainerReference(o.blobClient, bucket)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -132,7 +130,7 @@ func (o *objectStore) PutObject(bucket, key string, body io.Reader) error {
|
|||
return errors.WithStack(blob.CreateBlockBlobFromReader(body, nil))
|
||||
}
|
||||
|
||||
func (o *objectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
||||
func (o *ObjectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
||||
container, err := getContainerReference(o.blobClient, bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -151,7 +149,7 @@ func (o *objectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]string, error) {
|
||||
func (o *ObjectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]string, error) {
|
||||
container, err := getContainerReference(o.blobClient, bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -170,7 +168,7 @@ func (o *objectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]st
|
|||
return res.BlobPrefixes, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
||||
func (o *ObjectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
||||
container, err := getContainerReference(o.blobClient, bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -193,7 +191,7 @@ func (o *objectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) DeleteObject(bucket string, key string) error {
|
||||
func (o *ObjectStore) DeleteObject(bucket string, key string) error {
|
||||
container, err := getContainerReference(o.blobClient, bucket)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -207,7 +205,7 @@ func (o *objectStore) DeleteObject(bucket string, key string) error {
|
|||
return errors.WithStack(blob.Delete(nil))
|
||||
}
|
||||
|
||||
func (o *objectStore) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) {
|
||||
func (o *ObjectStore) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) {
|
||||
container, err := getContainerReference(o.blobClient, bucket)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
@ -33,8 +33,6 @@ import (
|
|||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -42,17 +40,17 @@ const (
|
|||
zoneSeparator = "__"
|
||||
)
|
||||
|
||||
type blockStore struct {
|
||||
type BlockStore struct {
|
||||
gce *compute.Service
|
||||
project string
|
||||
log logrus.FieldLogger
|
||||
}
|
||||
|
||||
func NewBlockStore(logger logrus.FieldLogger) cloudprovider.BlockStore {
|
||||
return &blockStore{log: logger}
|
||||
func NewBlockStore(logger logrus.FieldLogger) *BlockStore {
|
||||
return &BlockStore{log: logger}
|
||||
}
|
||||
|
||||
func (b *blockStore) Init(config map[string]string) error {
|
||||
func (b *BlockStore) Init(config map[string]string) error {
|
||||
project, err := extractProjectFromCreds()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -127,7 +125,7 @@ func parseRegion(volumeAZ string) (string, error) {
|
|||
}
|
||||
|
||||
// Retrieve the URLs for zones via the GCP API.
|
||||
func (b *blockStore) getZoneURLs(volumeAZ string) ([]string, error) {
|
||||
func (b *BlockStore) getZoneURLs(volumeAZ string) ([]string, error) {
|
||||
zones := strings.Split(volumeAZ, zoneSeparator)
|
||||
var zoneURLs []string
|
||||
for _, z := range zones {
|
||||
|
@ -142,7 +140,7 @@ func (b *blockStore) getZoneURLs(volumeAZ string) ([]string, error) {
|
|||
return zoneURLs, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (volumeID string, err error) {
|
||||
func (b *BlockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (volumeID string, err error) {
|
||||
// get the snapshot so we can apply its tags to the volume
|
||||
res, err := b.gce.Snapshots.Get(b.project, snapshotID).Do()
|
||||
if err != nil {
|
||||
|
@ -187,7 +185,7 @@ func (b *blockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ s
|
|||
return disk.Name, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
||||
func (b *BlockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
||||
var (
|
||||
res *compute.Disk
|
||||
err error
|
||||
|
@ -211,7 +209,7 @@ func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, e
|
|||
return res.Type, nil, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||
func (b *BlockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||
// snapshot names must adhere to RFC1035 and be 1-63 characters
|
||||
// long
|
||||
var snapshotName string
|
||||
|
@ -234,7 +232,7 @@ func (b *blockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]s
|
|||
}
|
||||
}
|
||||
|
||||
func (b *blockStore) createSnapshot(snapshotName, volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||
func (b *BlockStore) createSnapshot(snapshotName, volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||
disk, err := b.gce.Disks.Get(b.project, volumeAZ, volumeID).Do()
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
|
@ -253,7 +251,7 @@ func (b *blockStore) createSnapshot(snapshotName, volumeID, volumeAZ string, tag
|
|||
return gceSnap.Name, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) createRegionSnapshot(snapshotName, volumeID, volumeRegion string, tags map[string]string) (string, error) {
|
||||
func (b *BlockStore) createRegionSnapshot(snapshotName, volumeID, volumeRegion string, tags map[string]string) (string, error) {
|
||||
disk, err := b.gce.RegionDisks.Get(b.project, volumeRegion, volumeID).Do()
|
||||
if err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
|
@ -306,7 +304,7 @@ func getSnapshotTags(veleroTags map[string]string, diskDescription string, log l
|
|||
return string(tagsJSON)
|
||||
}
|
||||
|
||||
func (b *blockStore) DeleteSnapshot(snapshotID string) error {
|
||||
func (b *BlockStore) DeleteSnapshot(snapshotID string) error {
|
||||
_, err := b.gce.Snapshots.Delete(b.project, snapshotID).Do()
|
||||
|
||||
// if it's a 404 (not found) error, we don't need to return an error
|
||||
|
@ -321,7 +319,7 @@ func (b *blockStore) DeleteSnapshot(snapshotID string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *blockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, error) {
|
||||
func (b *BlockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, error) {
|
||||
pv := new(v1.PersistentVolume)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.UnstructuredContent(), pv); err != nil {
|
||||
return "", errors.WithStack(err)
|
||||
|
@ -338,7 +336,7 @@ func (b *blockStore) GetVolumeID(unstructuredPV runtime.Unstructured) (string, e
|
|||
return pv.Spec.GCEPersistentDisk.PDName, nil
|
||||
}
|
||||
|
||||
func (b *blockStore) SetVolumeID(unstructuredPV runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
||||
func (b *BlockStore) SetVolumeID(unstructuredPV runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
||||
pv := new(v1.PersistentVolume)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.UnstructuredContent(), pv); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
|
|
|
@ -31,7 +31,7 @@ import (
|
|||
)
|
||||
|
||||
func TestGetVolumeID(t *testing.T) {
|
||||
b := &blockStore{}
|
||||
b := &BlockStore{}
|
||||
|
||||
pv := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
|
@ -59,7 +59,7 @@ func TestGetVolumeID(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetVolumeID(t *testing.T) {
|
||||
b := &blockStore{}
|
||||
b := &BlockStore{}
|
||||
|
||||
pv := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{},
|
||||
|
|
|
@ -29,8 +29,6 @@ import (
|
|||
"golang.org/x/oauth2/google"
|
||||
"google.golang.org/api/iterator"
|
||||
"google.golang.org/api/option"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
const credentialsEnvVar = "GOOGLE_APPLICATION_CREDENTIALS"
|
||||
|
@ -49,7 +47,7 @@ func (w *writer) getWriteCloser(bucket, key string) io.WriteCloser {
|
|||
return w.client.Bucket(bucket).Object(key).NewWriter(context.Background())
|
||||
}
|
||||
|
||||
type objectStore struct {
|
||||
type ObjectStore struct {
|
||||
log logrus.FieldLogger
|
||||
client *storage.Client
|
||||
googleAccessID string
|
||||
|
@ -57,11 +55,11 @@ type objectStore struct {
|
|||
bucketWriter bucketWriter
|
||||
}
|
||||
|
||||
func NewObjectStore(logger logrus.FieldLogger) cloudprovider.ObjectStore {
|
||||
return &objectStore{log: logger}
|
||||
func NewObjectStore(logger logrus.FieldLogger) *ObjectStore {
|
||||
return &ObjectStore{log: logger}
|
||||
}
|
||||
|
||||
func (o *objectStore) Init(config map[string]string) error {
|
||||
func (o *ObjectStore) Init(config map[string]string) error {
|
||||
credentialsFile := os.Getenv(credentialsEnvVar)
|
||||
if credentialsFile == "" {
|
||||
return errors.Errorf("%s is undefined", credentialsEnvVar)
|
||||
|
@ -97,7 +95,7 @@ func (o *objectStore) Init(config map[string]string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *objectStore) PutObject(bucket, key string, body io.Reader) error {
|
||||
func (o *ObjectStore) PutObject(bucket, key string, body io.Reader) error {
|
||||
w := o.bucketWriter.getWriteCloser(bucket, key)
|
||||
|
||||
// The writer returned by NewWriter is asynchronous, so errors aren't guaranteed
|
||||
|
@ -113,7 +111,7 @@ func (o *objectStore) PutObject(bucket, key string, body io.Reader) error {
|
|||
return closeErr
|
||||
}
|
||||
|
||||
func (o *objectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
||||
func (o *ObjectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
||||
r, err := o.client.Bucket(bucket).Object(key).NewReader(context.Background())
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
|
@ -122,7 +120,7 @@ func (o *objectStore) GetObject(bucket, key string) (io.ReadCloser, error) {
|
|||
return r, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]string, error) {
|
||||
func (o *ObjectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]string, error) {
|
||||
q := &storage.Query{
|
||||
Prefix: prefix,
|
||||
Delimiter: delimiter,
|
||||
|
@ -148,7 +146,7 @@ func (o *objectStore) ListCommonPrefixes(bucket, prefix, delimiter string) ([]st
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (o *objectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
||||
func (o *ObjectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
||||
q := &storage.Query{
|
||||
Prefix: prefix,
|
||||
}
|
||||
|
@ -170,11 +168,11 @@ func (o *objectStore) ListObjects(bucket, prefix string) ([]string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *objectStore) DeleteObject(bucket, key string) error {
|
||||
func (o *ObjectStore) DeleteObject(bucket, key string) error {
|
||||
return errors.Wrapf(o.client.Bucket(bucket).Object(key).Delete(context.Background()), "error deleting object %s", key)
|
||||
}
|
||||
|
||||
func (o *objectStore) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) {
|
||||
func (o *ObjectStore) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) {
|
||||
return storage.SignedURL(bucket, key, &storage.SignedURLOptions{
|
||||
GoogleAccessID: o.googleAccessID,
|
||||
PrivateKey: o.privateKey,
|
||||
|
|
|
@ -89,7 +89,7 @@ func TestPutObject(t *testing.T) {
|
|||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
wc := newMockWriteCloser(test.writeErr, test.closeErr)
|
||||
o := NewObjectStore(velerotest.NewLogger()).(*objectStore)
|
||||
o := NewObjectStore(velerotest.NewLogger())
|
||||
o.bucketWriter = newFakeWriter(wc)
|
||||
|
||||
err := o.PutObject("bucket", "key", strings.NewReader("contents"))
|
||||
|
|
|
@ -86,7 +86,7 @@ func newGcpBlockStore(logger logrus.FieldLogger) (interface{}, error) {
|
|||
}
|
||||
|
||||
func newPVBackupItemAction(logger logrus.FieldLogger) (interface{}, error) {
|
||||
return backup.NewBackupPVAction(logger), nil
|
||||
return backup.NewPVCAction(logger), nil
|
||||
}
|
||||
|
||||
func newPodBackupItemAction(logger logrus.FieldLogger) (interface{}, error) {
|
||||
|
|
|
@ -42,6 +42,7 @@ import (
|
|||
persistencemocks "github.com/heptio/velero/pkg/persistence/mocks"
|
||||
"github.com/heptio/velero/pkg/plugin"
|
||||
pluginmocks "github.com/heptio/velero/pkg/plugin/mocks"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/util/logging"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
@ -50,7 +51,7 @@ type fakeBackupper struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
func (b *fakeBackupper) Backup(logger logrus.FieldLogger, backup *pkgbackup.Request, backupFile io.Writer, actions []pkgbackup.ItemAction, blockStoreGetter pkgbackup.BlockStoreGetter) error {
|
||||
func (b *fakeBackupper) Backup(logger logrus.FieldLogger, backup *pkgbackup.Request, backupFile io.Writer, actions []velero.BackupItemAction, blockStoreGetter pkgbackup.BlockStoreGetter) error {
|
||||
args := b.Called(logger, backup, backupFile, actions, blockStoreGetter)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
@ -314,7 +315,7 @@ func TestProcessBackupCompletions(t *testing.T) {
|
|||
pluginManager.On("GetBackupItemActions").Return(nil, nil)
|
||||
pluginManager.On("CleanupClients").Return(nil)
|
||||
|
||||
backupper.On("Backup", mock.Anything, mock.Anything, mock.Anything, []pkgbackup.ItemAction(nil), pluginManager).Return(nil)
|
||||
backupper.On("Backup", mock.Anything, mock.Anything, mock.Anything, []velero.BackupItemAction(nil), pluginManager).Return(nil)
|
||||
|
||||
// Ensure we have a CompletionTimestamp when uploading.
|
||||
// Failures will display the bytes in buf.
|
||||
|
|
|
@ -34,12 +34,12 @@ import (
|
|||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
pkgbackup "github.com/heptio/velero/pkg/backup"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
velerov1client "github.com/heptio/velero/pkg/generated/clientset/versioned/typed/velero/v1"
|
||||
informers "github.com/heptio/velero/pkg/generated/informers/externalversions/velero/v1"
|
||||
listers "github.com/heptio/velero/pkg/generated/listers/velero/v1"
|
||||
"github.com/heptio/velero/pkg/persistence"
|
||||
"github.com/heptio/velero/pkg/plugin"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/restic"
|
||||
"github.com/heptio/velero/pkg/util/kube"
|
||||
)
|
||||
|
@ -270,7 +270,7 @@ func (c *backupDeletionController) processRequest(req *v1.DeleteBackupRequest) e
|
|||
if snapshots, err := backupStore.GetBackupVolumeSnapshots(backup.Name); err != nil {
|
||||
errs = append(errs, errors.Wrap(err, "error getting backup's volume snapshots").Error())
|
||||
} else {
|
||||
blockStores := make(map[string]cloudprovider.BlockStore)
|
||||
blockStores := make(map[string]velero.BlockStore)
|
||||
|
||||
for _, snapshot := range snapshots {
|
||||
log.WithField("providerSnapshotID", snapshot.Status.ProviderSnapshotID).Info("Removing snapshot associated with backup")
|
||||
|
@ -365,7 +365,7 @@ func blockStoreForSnapshotLocation(
|
|||
namespace, snapshotLocationName string,
|
||||
snapshotLocationLister listers.VolumeSnapshotLocationLister,
|
||||
pluginManager plugin.Manager,
|
||||
) (cloudprovider.BlockStore, error) {
|
||||
) (velero.BlockStore, error) {
|
||||
snapshotLocation, err := snapshotLocationLister.VolumeSnapshotLocations(namespace).Get(snapshotLocationName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting volume snapshot location %s", snapshotLocationName)
|
||||
|
|
|
@ -41,6 +41,7 @@ import (
|
|||
"github.com/heptio/velero/pkg/metrics"
|
||||
"github.com/heptio/velero/pkg/persistence"
|
||||
"github.com/heptio/velero/pkg/plugin"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/restore"
|
||||
"github.com/heptio/velero/pkg/util/collections"
|
||||
kubeutil "github.com/heptio/velero/pkg/util/kube"
|
||||
|
@ -426,7 +427,7 @@ func (c *restoreController) fetchBackupInfo(backupName string, pluginManager plu
|
|||
|
||||
func (c *restoreController) runRestore(
|
||||
restore *api.Restore,
|
||||
actions []restore.ItemAction,
|
||||
actions []velero.RestoreItemAction,
|
||||
info backupInfo,
|
||||
pluginManager plugin.Manager,
|
||||
) (restoreResult, error) {
|
||||
|
|
|
@ -45,6 +45,7 @@ import (
|
|||
persistencemocks "github.com/heptio/velero/pkg/persistence/mocks"
|
||||
"github.com/heptio/velero/pkg/plugin"
|
||||
pluginmocks "github.com/heptio/velero/pkg/plugin/mocks"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/restore"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
"github.com/heptio/velero/pkg/volume"
|
||||
|
@ -922,7 +923,7 @@ func (r *fakeRestorer) Restore(
|
|||
backup *api.Backup,
|
||||
volumeSnapshots []*volume.Snapshot,
|
||||
backupReader io.Reader,
|
||||
actions []restore.ItemAction,
|
||||
actions []velero.RestoreItemAction,
|
||||
snapshotLocationLister listers.VolumeSnapshotLocationLister,
|
||||
blockStoreGetter restore.BlockStoreGetter,
|
||||
) (api.RestoreResult, api.RestoreResult) {
|
||||
|
|
|
@ -32,8 +32,8 @@ import (
|
|||
kerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
|
||||
velerov1api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/generated/clientset/versioned/scheme"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/volume"
|
||||
)
|
||||
|
||||
|
@ -62,16 +62,16 @@ type BackupStore interface {
|
|||
const DownloadURLTTL = 10 * time.Minute
|
||||
|
||||
type objectBackupStore struct {
|
||||
objectStore cloudprovider.ObjectStore
|
||||
objectStore velero.ObjectStore
|
||||
bucket string
|
||||
layout *ObjectStoreLayout
|
||||
logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
// ObjectStoreGetter is a type that can get a cloudprovider.ObjectStore
|
||||
// ObjectStoreGetter is a type that can get a velero.ObjectStore
|
||||
// from a provider name.
|
||||
type ObjectStoreGetter interface {
|
||||
GetObjectStore(provider string) (cloudprovider.ObjectStore, error)
|
||||
GetObjectStore(provider string) (velero.ObjectStore, error)
|
||||
}
|
||||
|
||||
func NewObjectBackupStore(location *velerov1api.BackupStorageLocation, objectStoreGetter ObjectStoreGetter, logger logrus.FieldLogger) (BackupStore, error) {
|
||||
|
@ -152,7 +152,7 @@ func (s *objectBackupStore) ListBackups() ([]string, error) {
|
|||
output := make([]string, 0, len(prefixes))
|
||||
|
||||
for _, prefix := range prefixes {
|
||||
// values returned from a call to cloudprovider.ObjectStore's
|
||||
// values returned from a call to ObjectStore's
|
||||
// ListCommonPrefixes method return the *full* prefix, inclusive
|
||||
// of s.backupsPrefix, and include the delimiter ("/") as a suffix. Trim
|
||||
// each of those off to get the backup name.
|
||||
|
@ -318,7 +318,7 @@ func convertMapKeys(m map[string]string, find, replace string) map[string]string
|
|||
return m
|
||||
}
|
||||
|
||||
func keyExists(objectStore cloudprovider.ObjectStore, bucket, prefix, key string) (bool, error) {
|
||||
func keyExists(objectStore velero.ObjectStore, bucket, prefix, key string) (bool, error) {
|
||||
keys, err := objectStore.ListObjects(bucket, prefix)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
@ -478,7 +478,7 @@ func seekToBeginning(r io.Reader) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func seekAndPutObject(objectStore cloudprovider.ObjectStore, bucket, key string, file io.Reader) error {
|
||||
func seekAndPutObject(objectStore velero.ObjectStore, bucket, key string, file io.Reader) error {
|
||||
if file == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
velerobackup "github.com/heptio/velero/pkg/backup"
|
||||
proto "github.com/heptio/velero/pkg/plugin/generated"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// BackupItemActionPlugin is an implementation of go-plugin's Plugin
|
||||
|
@ -70,13 +70,13 @@ func newBackupItemActionGRPCClient(base *clientBase, clientConn *grpc.ClientConn
|
|||
}
|
||||
}
|
||||
|
||||
func (c *BackupItemActionGRPCClient) AppliesTo() (velerobackup.ResourceSelector, error) {
|
||||
func (c *BackupItemActionGRPCClient) AppliesTo() (velero.ResourceSelector, error) {
|
||||
res, err := c.grpcClient.AppliesTo(context.Background(), &proto.AppliesToRequest{Plugin: c.plugin})
|
||||
if err != nil {
|
||||
return velerobackup.ResourceSelector{}, err
|
||||
return velero.ResourceSelector{}, err
|
||||
}
|
||||
|
||||
return velerobackup.ResourceSelector{
|
||||
return velero.ResourceSelector{
|
||||
IncludedNamespaces: res.IncludedNamespaces,
|
||||
ExcludedNamespaces: res.ExcludedNamespaces,
|
||||
IncludedResources: res.IncludedResources,
|
||||
|
@ -85,7 +85,7 @@ func (c *BackupItemActionGRPCClient) AppliesTo() (velerobackup.ResourceSelector,
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (c *BackupItemActionGRPCClient) Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []velerobackup.ResourceIdentifier, error) {
|
||||
func (c *BackupItemActionGRPCClient) Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
|
||||
itemJSON, err := json.Marshal(item.UnstructuredContent())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -112,10 +112,10 @@ func (c *BackupItemActionGRPCClient) Execute(item runtime.Unstructured, backup *
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
var additionalItems []velerobackup.ResourceIdentifier
|
||||
var additionalItems []velero.ResourceIdentifier
|
||||
|
||||
for _, itm := range res.AdditionalItems {
|
||||
newItem := velerobackup.ResourceIdentifier{
|
||||
newItem := velero.ResourceIdentifier{
|
||||
GroupResource: schema.GroupResource{
|
||||
Group: itm.Group,
|
||||
Resource: itm.Resource,
|
||||
|
@ -146,13 +146,13 @@ type BackupItemActionGRPCServer struct {
|
|||
mux *serverMux
|
||||
}
|
||||
|
||||
func (s *BackupItemActionGRPCServer) getImpl(name string) (velerobackup.ItemAction, error) {
|
||||
func (s *BackupItemActionGRPCServer) getImpl(name string) (velero.BackupItemAction, error) {
|
||||
impl, err := s.mux.getHandler(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
itemAction, ok := impl.(velerobackup.ItemAction)
|
||||
itemAction, ok := impl.(velero.BackupItemAction)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not a backup item action", impl)
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ func (s *BackupItemActionGRPCServer) Execute(ctx context.Context, req *proto.Exe
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func backupResourceIdentifierToProto(id velerobackup.ResourceIdentifier) *proto.ResourceIdentifier {
|
||||
func backupResourceIdentifierToProto(id velero.ResourceIdentifier) *proto.ResourceIdentifier {
|
||||
return &proto.ResourceIdentifier{
|
||||
Group: id.Group,
|
||||
Resource: id.Resource,
|
||||
|
|
|
@ -29,9 +29,9 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/backup"
|
||||
"github.com/heptio/velero/pkg/backup/mocks"
|
||||
proto "github.com/heptio/velero/pkg/plugin/generated"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
||||
|
@ -93,7 +93,7 @@ func TestBackupItemActionGRPCServerExecute(t *testing.T) {
|
|||
backup []byte
|
||||
item []byte
|
||||
implUpdatedItem runtime.Unstructured
|
||||
implAdditionalItems []backup.ResourceIdentifier
|
||||
implAdditionalItems []velero.ResourceIdentifier
|
||||
implError error
|
||||
expectError bool
|
||||
skipMock bool
|
||||
|
@ -129,7 +129,7 @@ func TestBackupItemActionGRPCServerExecute(t *testing.T) {
|
|||
item: validItem,
|
||||
backup: validBackup,
|
||||
implUpdatedItem: &validItemObject,
|
||||
implAdditionalItems: []backup.ResourceIdentifier{
|
||||
implAdditionalItems: []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: schema.GroupResource{Group: "v1", Resource: "pods"},
|
||||
Namespace: "myns",
|
||||
|
|
|
@ -26,8 +26,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
proto "github.com/heptio/velero/pkg/plugin/generated"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// BlockStorePlugin is an implementation of go-plugin's Plugin
|
||||
|
@ -203,13 +203,13 @@ type BlockStoreGRPCServer struct {
|
|||
mux *serverMux
|
||||
}
|
||||
|
||||
func (s *BlockStoreGRPCServer) getImpl(name string) (cloudprovider.BlockStore, error) {
|
||||
func (s *BlockStoreGRPCServer) getImpl(name string) (velero.BlockStore, error) {
|
||||
impl, err := s.mux.getHandler(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockStore, ok := impl.(cloudprovider.BlockStore)
|
||||
blockStore, ok := impl.(velero.BlockStore)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not a block store", impl)
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ type clientDispenser struct {
|
|||
logger logrus.FieldLogger
|
||||
// clienConn is shared among all implementations for this client.
|
||||
clientConn *grpc.ClientConn
|
||||
// initFunc returns a client that implements a plugin interface, such as cloudprovider.ObjectStore.
|
||||
// initFunc returns a client that implements a plugin interface, such as ObjectStore.
|
||||
initFunc clientInitFunc
|
||||
// clients keeps track of all the initialized implementations.
|
||||
clients map[string]interface{}
|
||||
|
|
|
@ -21,30 +21,28 @@ import (
|
|||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/heptio/velero/pkg/backup"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/restore"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// Manager manages the lifecycles of plugins.
|
||||
type Manager interface {
|
||||
// GetObjectStore returns the ObjectStore plugin for name.
|
||||
GetObjectStore(name string) (cloudprovider.ObjectStore, error)
|
||||
GetObjectStore(name string) (velero.ObjectStore, error)
|
||||
|
||||
// GetBlockStore returns the BlockStore plugin for name.
|
||||
GetBlockStore(name string) (cloudprovider.BlockStore, error)
|
||||
GetBlockStore(name string) (velero.BlockStore, error)
|
||||
|
||||
// GetBackupItemActions returns all backup item action plugins.
|
||||
GetBackupItemActions() ([]backup.ItemAction, error)
|
||||
GetBackupItemActions() ([]velero.BackupItemAction, error)
|
||||
|
||||
// GetBackupItemAction returns the backup item action plugin for name.
|
||||
GetBackupItemAction(name string) (backup.ItemAction, error)
|
||||
GetBackupItemAction(name string) (velero.BackupItemAction, error)
|
||||
|
||||
// GetRestoreItemActions returns all restore item action plugins.
|
||||
GetRestoreItemActions() ([]restore.ItemAction, error)
|
||||
GetRestoreItemActions() ([]velero.RestoreItemAction, error)
|
||||
|
||||
// GetRestoreItemAction returns the restore item action plugin for name.
|
||||
GetRestoreItemAction(name string) (restore.ItemAction, error)
|
||||
GetRestoreItemAction(name string) (velero.RestoreItemAction, error)
|
||||
|
||||
// CleanupClients terminates all of the Manager's running plugin processes.
|
||||
CleanupClients()
|
||||
|
@ -124,7 +122,7 @@ func (m *manager) getRestartableProcess(kind PluginKind, name string) (Restartab
|
|||
}
|
||||
|
||||
// GetObjectStore returns a restartableObjectStore for name.
|
||||
func (m *manager) GetObjectStore(name string) (cloudprovider.ObjectStore, error) {
|
||||
func (m *manager) GetObjectStore(name string) (velero.ObjectStore, error) {
|
||||
restartableProcess, err := m.getRestartableProcess(PluginKindObjectStore, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -136,7 +134,7 @@ func (m *manager) GetObjectStore(name string) (cloudprovider.ObjectStore, error)
|
|||
}
|
||||
|
||||
// GetBlockStore returns a restartableBlockStore for name.
|
||||
func (m *manager) GetBlockStore(name string) (cloudprovider.BlockStore, error) {
|
||||
func (m *manager) GetBlockStore(name string) (velero.BlockStore, error) {
|
||||
restartableProcess, err := m.getRestartableProcess(PluginKindBlockStore, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -148,10 +146,10 @@ func (m *manager) GetBlockStore(name string) (cloudprovider.BlockStore, error) {
|
|||
}
|
||||
|
||||
// GetBackupItemActions returns all backup item actions as restartableBackupItemActions.
|
||||
func (m *manager) GetBackupItemActions() ([]backup.ItemAction, error) {
|
||||
func (m *manager) GetBackupItemActions() ([]velero.BackupItemAction, error) {
|
||||
list := m.registry.List(PluginKindBackupItemAction)
|
||||
|
||||
actions := make([]backup.ItemAction, 0, len(list))
|
||||
actions := make([]velero.BackupItemAction, 0, len(list))
|
||||
|
||||
for i := range list {
|
||||
id := list[i]
|
||||
|
@ -168,7 +166,7 @@ func (m *manager) GetBackupItemActions() ([]backup.ItemAction, error) {
|
|||
}
|
||||
|
||||
// GetBackupItemAction returns a restartableBackupItemAction for name.
|
||||
func (m *manager) GetBackupItemAction(name string) (backup.ItemAction, error) {
|
||||
func (m *manager) GetBackupItemAction(name string) (velero.BackupItemAction, error) {
|
||||
restartableProcess, err := m.getRestartableProcess(PluginKindBackupItemAction, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -179,10 +177,10 @@ func (m *manager) GetBackupItemAction(name string) (backup.ItemAction, error) {
|
|||
}
|
||||
|
||||
// GetRestoreItemActions returns all restore item actions as restartableRestoreItemActions.
|
||||
func (m *manager) GetRestoreItemActions() ([]restore.ItemAction, error) {
|
||||
func (m *manager) GetRestoreItemActions() ([]velero.RestoreItemAction, error) {
|
||||
list := m.registry.List(PluginKindRestoreItemAction)
|
||||
|
||||
actions := make([]restore.ItemAction, 0, len(list))
|
||||
actions := make([]velero.RestoreItemAction, 0, len(list))
|
||||
|
||||
for i := range list {
|
||||
id := list[i]
|
||||
|
@ -199,7 +197,7 @@ func (m *manager) GetRestoreItemActions() ([]restore.ItemAction, error) {
|
|||
}
|
||||
|
||||
// GetRestoreItemAction returns a restartableRestoreItemAction for name.
|
||||
func (m *manager) GetRestoreItemAction(name string) (restore.ItemAction, error) {
|
||||
func (m *manager) GetRestoreItemAction(name string) (velero.RestoreItemAction, error) {
|
||||
restartableProcess, err := m.getRestartableProcess(PluginKindRestoreItemAction, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -16,11 +16,11 @@ limitations under the License.
|
|||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
package mocks
|
||||
|
||||
import backup "github.com/heptio/velero/pkg/backup"
|
||||
import cloudprovider "github.com/heptio/velero/pkg/cloudprovider"
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
import restore "github.com/heptio/velero/pkg/restore"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// Manager is an autogenerated mock type for the Manager type
|
||||
type Manager struct {
|
||||
|
@ -33,15 +33,15 @@ func (_m *Manager) CleanupClients() {
|
|||
}
|
||||
|
||||
// GetBackupItemAction provides a mock function with given fields: name
|
||||
func (_m *Manager) GetBackupItemAction(name string) (backup.ItemAction, error) {
|
||||
func (_m *Manager) GetBackupItemAction(name string) (velero.BackupItemAction, error) {
|
||||
ret := _m.Called(name)
|
||||
|
||||
var r0 backup.ItemAction
|
||||
if rf, ok := ret.Get(0).(func(string) backup.ItemAction); ok {
|
||||
var r0 velero.BackupItemAction
|
||||
if rf, ok := ret.Get(0).(func(string) velero.BackupItemAction); ok {
|
||||
r0 = rf(name)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(backup.ItemAction)
|
||||
r0 = ret.Get(0).(velero.BackupItemAction)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,15 +56,15 @@ func (_m *Manager) GetBackupItemAction(name string) (backup.ItemAction, error) {
|
|||
}
|
||||
|
||||
// GetBackupItemActions provides a mock function with given fields:
|
||||
func (_m *Manager) GetBackupItemActions() ([]backup.ItemAction, error) {
|
||||
func (_m *Manager) GetBackupItemActions() ([]velero.BackupItemAction, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []backup.ItemAction
|
||||
if rf, ok := ret.Get(0).(func() []backup.ItemAction); ok {
|
||||
var r0 []velero.BackupItemAction
|
||||
if rf, ok := ret.Get(0).(func() []velero.BackupItemAction); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]backup.ItemAction)
|
||||
r0 = ret.Get(0).([]velero.BackupItemAction)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,15 +79,15 @@ func (_m *Manager) GetBackupItemActions() ([]backup.ItemAction, error) {
|
|||
}
|
||||
|
||||
// GetBlockStore provides a mock function with given fields: name
|
||||
func (_m *Manager) GetBlockStore(name string) (cloudprovider.BlockStore, error) {
|
||||
func (_m *Manager) GetBlockStore(name string) (velero.BlockStore, error) {
|
||||
ret := _m.Called(name)
|
||||
|
||||
var r0 cloudprovider.BlockStore
|
||||
if rf, ok := ret.Get(0).(func(string) cloudprovider.BlockStore); ok {
|
||||
var r0 velero.BlockStore
|
||||
if rf, ok := ret.Get(0).(func(string) velero.BlockStore); ok {
|
||||
r0 = rf(name)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(cloudprovider.BlockStore)
|
||||
r0 = ret.Get(0).(velero.BlockStore)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,15 +102,15 @@ func (_m *Manager) GetBlockStore(name string) (cloudprovider.BlockStore, error)
|
|||
}
|
||||
|
||||
// GetObjectStore provides a mock function with given fields: name
|
||||
func (_m *Manager) GetObjectStore(name string) (cloudprovider.ObjectStore, error) {
|
||||
func (_m *Manager) GetObjectStore(name string) (velero.ObjectStore, error) {
|
||||
ret := _m.Called(name)
|
||||
|
||||
var r0 cloudprovider.ObjectStore
|
||||
if rf, ok := ret.Get(0).(func(string) cloudprovider.ObjectStore); ok {
|
||||
var r0 velero.ObjectStore
|
||||
if rf, ok := ret.Get(0).(func(string) velero.ObjectStore); ok {
|
||||
r0 = rf(name)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(cloudprovider.ObjectStore)
|
||||
r0 = ret.Get(0).(velero.ObjectStore)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,15 +125,15 @@ func (_m *Manager) GetObjectStore(name string) (cloudprovider.ObjectStore, error
|
|||
}
|
||||
|
||||
// GetRestoreItemAction provides a mock function with given fields: name
|
||||
func (_m *Manager) GetRestoreItemAction(name string) (restore.ItemAction, error) {
|
||||
func (_m *Manager) GetRestoreItemAction(name string) (velero.RestoreItemAction, error) {
|
||||
ret := _m.Called(name)
|
||||
|
||||
var r0 restore.ItemAction
|
||||
if rf, ok := ret.Get(0).(func(string) restore.ItemAction); ok {
|
||||
var r0 velero.RestoreItemAction
|
||||
if rf, ok := ret.Get(0).(func(string) velero.RestoreItemAction); ok {
|
||||
r0 = rf(name)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(restore.ItemAction)
|
||||
r0 = ret.Get(0).(velero.RestoreItemAction)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,15 +148,15 @@ func (_m *Manager) GetRestoreItemAction(name string) (restore.ItemAction, error)
|
|||
}
|
||||
|
||||
// GetRestoreItemActions provides a mock function with given fields:
|
||||
func (_m *Manager) GetRestoreItemActions() ([]restore.ItemAction, error) {
|
||||
func (_m *Manager) GetRestoreItemActions() ([]velero.RestoreItemAction, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []restore.ItemAction
|
||||
if rf, ok := ret.Get(0).(func() []restore.ItemAction); ok {
|
||||
var r0 []velero.RestoreItemAction
|
||||
if rf, ok := ret.Get(0).(func() []velero.RestoreItemAction); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]restore.ItemAction)
|
||||
r0 = ret.Get(0).([]velero.RestoreItemAction)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ import (
|
|||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
proto "github.com/heptio/velero/pkg/plugin/generated"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
const byteChunkSize = 16384
|
||||
|
@ -56,7 +56,7 @@ func (p *ObjectStorePlugin) GRPCClient(c *grpc.ClientConn) (interface{}, error)
|
|||
|
||||
}
|
||||
|
||||
// ObjectStoreGRPCClient implements the cloudprovider.ObjectStore interface and uses a
|
||||
// ObjectStoreGRPCClient implements the ObjectStore interface and uses a
|
||||
// gRPC client to make calls to the plugin server.
|
||||
type ObjectStoreGRPCClient struct {
|
||||
*clientBase
|
||||
|
@ -199,13 +199,13 @@ type ObjectStoreGRPCServer struct {
|
|||
mux *serverMux
|
||||
}
|
||||
|
||||
func (s *ObjectStoreGRPCServer) getImpl(name string) (cloudprovider.ObjectStore, error) {
|
||||
func (s *ObjectStoreGRPCServer) getImpl(name string) (velero.ObjectStore, error) {
|
||||
impl, err := s.mux.getHandler(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
itemAction, ok := impl.(cloudprovider.ObjectStore)
|
||||
itemAction, ok := impl.(velero.ObjectStore)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not an object store", impl)
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ func (r *process) dispense(key kindAndName) (interface{}, error) {
|
|||
if key.name == "" {
|
||||
return nil, errors.Errorf("%s plugin requested but name is missing", key.kind.String())
|
||||
}
|
||||
// Get the instance that implements our plugin interface (e.g. cloudprovider.ObjectStore) that is a gRPC-based
|
||||
// Get the instance that implements our plugin interface (e.g. ObjectStore) that is a gRPC-based
|
||||
// client
|
||||
dispensed = clientDispenser.clientFor(key.name)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/backup"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// restartableBackupItemAction is a backup item action for a given implementation (such as "pod"). It is associated with
|
||||
|
@ -43,22 +43,22 @@ func newRestartableBackupItemAction(name string, sharedPluginProcess Restartable
|
|||
|
||||
// getBackupItemAction returns the backup item action for this restartableBackupItemAction. It does *not* restart the
|
||||
// plugin process.
|
||||
func (r *restartableBackupItemAction) getBackupItemAction() (backup.ItemAction, error) {
|
||||
func (r *restartableBackupItemAction) getBackupItemAction() (velero.BackupItemAction, error) {
|
||||
plugin, err := r.sharedPluginProcess.getByKindAndName(r.key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
backupItemAction, ok := plugin.(backup.ItemAction)
|
||||
backupItemAction, ok := plugin.(velero.BackupItemAction)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not a backup.ItemAction!", plugin)
|
||||
return nil, errors.Errorf("%T is not a BackupItemAction!", plugin)
|
||||
}
|
||||
|
||||
return backupItemAction, nil
|
||||
}
|
||||
|
||||
// getDelegate restarts the plugin process (if needed) and returns the backup item action for this restartableBackupItemAction.
|
||||
func (r *restartableBackupItemAction) getDelegate() (backup.ItemAction, error) {
|
||||
func (r *restartableBackupItemAction) getDelegate() (velero.BackupItemAction, error) {
|
||||
if err := r.sharedPluginProcess.resetIfNeeded(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -67,17 +67,17 @@ func (r *restartableBackupItemAction) getDelegate() (backup.ItemAction, error) {
|
|||
}
|
||||
|
||||
// AppliesTo restarts the plugin's process if needed, then delegates the call.
|
||||
func (r *restartableBackupItemAction) AppliesTo() (backup.ResourceSelector, error) {
|
||||
func (r *restartableBackupItemAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
delegate, err := r.getDelegate()
|
||||
if err != nil {
|
||||
return backup.ResourceSelector{}, err
|
||||
return velero.ResourceSelector{}, err
|
||||
}
|
||||
|
||||
return delegate.AppliesTo()
|
||||
}
|
||||
|
||||
// Execute restarts the plugin's process if needed, then delegates the call.
|
||||
func (r *restartableBackupItemAction) Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []backup.ResourceIdentifier, error) {
|
||||
func (r *restartableBackupItemAction) Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error) {
|
||||
delegate, err := r.getDelegate()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
@ -26,8 +26,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/backup"
|
||||
"github.com/heptio/velero/pkg/backup/mocks"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
func TestRestartableGetBackupItemAction(t *testing.T) {
|
||||
|
@ -45,7 +45,7 @@ func TestRestartableGetBackupItemAction(t *testing.T) {
|
|||
{
|
||||
name: "wrong type",
|
||||
plugin: 3,
|
||||
expectedError: "int is not a backup.ItemAction!",
|
||||
expectedError: "int is not a BackupItemAction!",
|
||||
},
|
||||
{
|
||||
name: "happy path",
|
||||
|
@ -113,7 +113,7 @@ func TestRestartableBackupItemActionDelegatedFunctions(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
additionalItems := []backup.ResourceIdentifier{
|
||||
additionalItems := []velero.ResourceIdentifier{
|
||||
{
|
||||
GroupResource: schema.GroupResource{Group: "velero.io", Resource: "backups"},
|
||||
},
|
||||
|
@ -134,13 +134,13 @@ func TestRestartableBackupItemActionDelegatedFunctions(t *testing.T) {
|
|||
restartableDelegateTest{
|
||||
function: "AppliesTo",
|
||||
inputs: []interface{}{},
|
||||
expectedErrorOutputs: []interface{}{backup.ResourceSelector{}, errors.Errorf("reset error")},
|
||||
expectedDelegateOutputs: []interface{}{backup.ResourceSelector{IncludedNamespaces: []string{"a"}}, errors.Errorf("delegate error")},
|
||||
expectedErrorOutputs: []interface{}{velero.ResourceSelector{}, errors.Errorf("reset error")},
|
||||
expectedDelegateOutputs: []interface{}{velero.ResourceSelector{IncludedNamespaces: []string{"a"}}, errors.Errorf("delegate error")},
|
||||
},
|
||||
restartableDelegateTest{
|
||||
function: "Execute",
|
||||
inputs: []interface{}{pv, b},
|
||||
expectedErrorOutputs: []interface{}{nil, ([]backup.ResourceIdentifier)(nil), errors.Errorf("reset error")},
|
||||
expectedErrorOutputs: []interface{}{nil, ([]velero.ResourceIdentifier)(nil), errors.Errorf("reset error")},
|
||||
expectedDelegateOutputs: []interface{}{pvToReturn, additionalItems, errors.Errorf("delegate error")},
|
||||
},
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// restartableBlockStore is an object store for a given implementation (such as "aws"). It is associated with
|
||||
|
@ -48,31 +48,31 @@ func newRestartableBlockStore(name string, sharedPluginProcess RestartableProces
|
|||
|
||||
// reinitialize reinitializes a re-dispensed plugin using the initial data passed to Init().
|
||||
func (r *restartableBlockStore) reinitialize(dispensed interface{}) error {
|
||||
blockStore, ok := dispensed.(cloudprovider.BlockStore)
|
||||
blockStore, ok := dispensed.(velero.BlockStore)
|
||||
if !ok {
|
||||
return errors.Errorf("%T is not a cloudprovider.BlockStore!", dispensed)
|
||||
return errors.Errorf("%T is not a BlockStore!", dispensed)
|
||||
}
|
||||
return r.init(blockStore, r.config)
|
||||
}
|
||||
|
||||
// getBlockStore returns the block store for this restartableBlockStore. It does *not* restart the
|
||||
// plugin process.
|
||||
func (r *restartableBlockStore) getBlockStore() (cloudprovider.BlockStore, error) {
|
||||
func (r *restartableBlockStore) getBlockStore() (velero.BlockStore, error) {
|
||||
plugin, err := r.sharedPluginProcess.getByKindAndName(r.key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockStore, ok := plugin.(cloudprovider.BlockStore)
|
||||
blockStore, ok := plugin.(velero.BlockStore)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not a cloudprovider.BlockStore!", plugin)
|
||||
return nil, errors.Errorf("%T is not a BlockStore!", plugin)
|
||||
}
|
||||
|
||||
return blockStore, nil
|
||||
}
|
||||
|
||||
// getDelegate restarts the plugin process (if needed) and returns the block store for this restartableBlockStore.
|
||||
func (r *restartableBlockStore) getDelegate() (cloudprovider.BlockStore, error) {
|
||||
func (r *restartableBlockStore) getDelegate() (velero.BlockStore, error) {
|
||||
if err := r.sharedPluginProcess.resetIfNeeded(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ func (r *restartableBlockStore) Init(config map[string]string) error {
|
|||
|
||||
// init calls Init on blockStore with config. This is split out from Init() so that both Init() and reinitialize() may
|
||||
// call it using a specific BlockStore.
|
||||
func (r *restartableBlockStore) init(blockStore cloudprovider.BlockStore, config map[string]string) error {
|
||||
func (r *restartableBlockStore) init(blockStore velero.BlockStore, config map[string]string) error {
|
||||
return blockStore.Init(config)
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ func TestRestartableGetBlockStore(t *testing.T) {
|
|||
{
|
||||
name: "wrong type",
|
||||
plugin: 3,
|
||||
expectedError: "int is not a cloudprovider.BlockStore!",
|
||||
expectedError: "int is not a BlockStore!",
|
||||
},
|
||||
{
|
||||
name: "happy path",
|
||||
|
@ -93,7 +93,7 @@ func TestRestartableBlockStoreReinitialize(t *testing.T) {
|
|||
}
|
||||
|
||||
err := r.reinitialize(3)
|
||||
assert.EqualError(t, err, "int is not a cloudprovider.BlockStore!")
|
||||
assert.EqualError(t, err, "int is not a BlockStore!")
|
||||
|
||||
blockStore := new(mocks.BlockStore)
|
||||
blockStore.Test(t)
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// restartableObjectStore is an object store for a given implementation (such as "aws"). It is associated with
|
||||
|
@ -52,9 +52,9 @@ func newRestartableObjectStore(name string, sharedPluginProcess RestartableProce
|
|||
|
||||
// reinitialize reinitializes a re-dispensed plugin using the initial data passed to Init().
|
||||
func (r *restartableObjectStore) reinitialize(dispensed interface{}) error {
|
||||
objectStore, ok := dispensed.(cloudprovider.ObjectStore)
|
||||
objectStore, ok := dispensed.(velero.ObjectStore)
|
||||
if !ok {
|
||||
return errors.Errorf("%T is not a cloudprovider.ObjectStore!", dispensed)
|
||||
return errors.Errorf("%T is not a ObjectStore!", dispensed)
|
||||
}
|
||||
|
||||
return r.init(objectStore, r.config)
|
||||
|
@ -62,22 +62,22 @@ func (r *restartableObjectStore) reinitialize(dispensed interface{}) error {
|
|||
|
||||
// getObjectStore returns the object store for this restartableObjectStore. It does *not* restart the
|
||||
// plugin process.
|
||||
func (r *restartableObjectStore) getObjectStore() (cloudprovider.ObjectStore, error) {
|
||||
func (r *restartableObjectStore) getObjectStore() (velero.ObjectStore, error) {
|
||||
plugin, err := r.sharedPluginProcess.getByKindAndName(r.key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
objectStore, ok := plugin.(cloudprovider.ObjectStore)
|
||||
objectStore, ok := plugin.(velero.ObjectStore)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not a cloudprovider.ObjectStore!", plugin)
|
||||
return nil, errors.Errorf("%T is not a ObjectStore!", plugin)
|
||||
}
|
||||
|
||||
return objectStore, nil
|
||||
}
|
||||
|
||||
// getDelegate restarts the plugin process (if needed) and returns the object store for this restartableObjectStore.
|
||||
func (r *restartableObjectStore) getDelegate() (cloudprovider.ObjectStore, error) {
|
||||
func (r *restartableObjectStore) getDelegate() (velero.ObjectStore, error) {
|
||||
if err := r.sharedPluginProcess.resetIfNeeded(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ func (r *restartableObjectStore) Init(config map[string]string) error {
|
|||
|
||||
// init calls Init on objectStore with config. This is split out from Init() so that both Init() and reinitialize() may
|
||||
// call it using a specific ObjectStore.
|
||||
func (r *restartableObjectStore) init(objectStore cloudprovider.ObjectStore, config map[string]string) error {
|
||||
func (r *restartableObjectStore) init(objectStore velero.ObjectStore, config map[string]string) error {
|
||||
return objectStore.Init(config)
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestRestartableGetObjectStore(t *testing.T) {
|
|||
{
|
||||
name: "wrong type",
|
||||
plugin: 3,
|
||||
expectedError: "int is not a cloudprovider.ObjectStore!",
|
||||
expectedError: "int is not a ObjectStore!",
|
||||
},
|
||||
{
|
||||
name: "happy path",
|
||||
|
@ -94,7 +94,7 @@ func TestRestartableObjectStoreReinitialize(t *testing.T) {
|
|||
}
|
||||
|
||||
err := r.reinitialize(3)
|
||||
assert.EqualError(t, err, "int is not a cloudprovider.ObjectStore!")
|
||||
assert.EqualError(t, err, "int is not a ObjectStore!")
|
||||
|
||||
objectStore := new(cloudprovidermocks.ObjectStore)
|
||||
objectStore.Test(t)
|
||||
|
|
|
@ -18,7 +18,7 @@ package plugin
|
|||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/heptio/velero/pkg/restore"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// restartableRestoreItemAction is a restore item action for a given implementation (such as "pod"). It is associated with
|
||||
|
@ -42,22 +42,22 @@ func newRestartableRestoreItemAction(name string, sharedPluginProcess Restartabl
|
|||
|
||||
// getRestoreItemAction returns the restore item action for this restartableRestoreItemAction. It does *not* restart the
|
||||
// plugin process.
|
||||
func (r *restartableRestoreItemAction) getRestoreItemAction() (restore.ItemAction, error) {
|
||||
func (r *restartableRestoreItemAction) getRestoreItemAction() (velero.RestoreItemAction, error) {
|
||||
plugin, err := r.sharedPluginProcess.getByKindAndName(r.key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
restoreItemAction, ok := plugin.(restore.ItemAction)
|
||||
restoreItemAction, ok := plugin.(velero.RestoreItemAction)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not a restore.ItemAction!", plugin)
|
||||
return nil, errors.Errorf("%T is not a RestoreItemAction!", plugin)
|
||||
}
|
||||
|
||||
return restoreItemAction, nil
|
||||
}
|
||||
|
||||
// getDelegate restarts the plugin process (if needed) and returns the restore item action for this restartableRestoreItemAction.
|
||||
func (r *restartableRestoreItemAction) getDelegate() (restore.ItemAction, error) {
|
||||
func (r *restartableRestoreItemAction) getDelegate() (velero.RestoreItemAction, error) {
|
||||
if err := r.sharedPluginProcess.resetIfNeeded(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -66,17 +66,17 @@ func (r *restartableRestoreItemAction) getDelegate() (restore.ItemAction, error)
|
|||
}
|
||||
|
||||
// AppliesTo restarts the plugin's process if needed, then delegates the call.
|
||||
func (r *restartableRestoreItemAction) AppliesTo() (restore.ResourceSelector, error) {
|
||||
func (r *restartableRestoreItemAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
delegate, err := r.getDelegate()
|
||||
if err != nil {
|
||||
return restore.ResourceSelector{}, err
|
||||
return velero.ResourceSelector{}, err
|
||||
}
|
||||
|
||||
return delegate.AppliesTo()
|
||||
}
|
||||
|
||||
// Execute restarts the plugin's process if needed, then delegates the call.
|
||||
func (r *restartableRestoreItemAction) Execute(input *restore.RestoreItemActionExecuteInput) (*restore.RestoreItemActionExecuteOutput, error) {
|
||||
func (r *restartableRestoreItemAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
delegate, err := r.getDelegate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -25,7 +25,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
v1 "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/restore"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/restore/mocks"
|
||||
)
|
||||
|
||||
|
@ -44,7 +44,7 @@ func TestRestartableGetRestoreItemAction(t *testing.T) {
|
|||
{
|
||||
name: "wrong type",
|
||||
plugin: 3,
|
||||
expectedError: "int is not a restore.ItemAction!",
|
||||
expectedError: "int is not a RestoreItemAction!",
|
||||
},
|
||||
{
|
||||
name: "happy path",
|
||||
|
@ -104,13 +104,13 @@ func TestRestartableRestoreItemActionDelegatedFunctions(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
input := &restore.RestoreItemActionExecuteInput{
|
||||
input := &velero.RestoreItemActionExecuteInput{
|
||||
Item: pv,
|
||||
ItemFromBackup: pv,
|
||||
Restore: new(v1.Restore),
|
||||
}
|
||||
|
||||
output := &restore.RestoreItemActionExecuteOutput{
|
||||
output := &velero.RestoreItemActionExecuteOutput{
|
||||
UpdatedItem: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"color": "green",
|
||||
|
@ -134,8 +134,8 @@ func TestRestartableRestoreItemActionDelegatedFunctions(t *testing.T) {
|
|||
restartableDelegateTest{
|
||||
function: "AppliesTo",
|
||||
inputs: []interface{}{},
|
||||
expectedErrorOutputs: []interface{}{restore.ResourceSelector{}, errors.Errorf("reset error")},
|
||||
expectedDelegateOutputs: []interface{}{restore.ResourceSelector{IncludedNamespaces: []string{"a"}}, errors.Errorf("delegate error")},
|
||||
expectedErrorOutputs: []interface{}{velero.ResourceSelector{}, errors.Errorf("reset error")},
|
||||
expectedDelegateOutputs: []interface{}{velero.ResourceSelector{IncludedNamespaces: []string{"a"}}, errors.Errorf("delegate error")},
|
||||
},
|
||||
restartableDelegateTest{
|
||||
function: "Execute",
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
proto "github.com/heptio/velero/pkg/plugin/generated"
|
||||
"github.com/heptio/velero/pkg/restore"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// RestoreItemActionPlugin is an implementation of go-plugin's Plugin
|
||||
|
@ -38,7 +38,7 @@ type RestoreItemActionPlugin struct {
|
|||
*pluginBase
|
||||
}
|
||||
|
||||
var _ restore.ItemAction = &RestoreItemActionGRPCClient{}
|
||||
var _ velero.RestoreItemAction = &RestoreItemActionGRPCClient{}
|
||||
|
||||
// NewRestoreItemActionPlugin constructs a RestoreItemActionPlugin.
|
||||
func NewRestoreItemActionPlugin(options ...pluginOption) *RestoreItemActionPlugin {
|
||||
|
@ -70,13 +70,13 @@ func newRestoreItemActionGRPCClient(base *clientBase, clientConn *grpc.ClientCon
|
|||
}
|
||||
}
|
||||
|
||||
func (c *RestoreItemActionGRPCClient) AppliesTo() (restore.ResourceSelector, error) {
|
||||
func (c *RestoreItemActionGRPCClient) AppliesTo() (velero.ResourceSelector, error) {
|
||||
res, err := c.grpcClient.AppliesTo(context.Background(), &proto.AppliesToRequest{Plugin: c.plugin})
|
||||
if err != nil {
|
||||
return restore.ResourceSelector{}, err
|
||||
return velero.ResourceSelector{}, err
|
||||
}
|
||||
|
||||
return restore.ResourceSelector{
|
||||
return velero.ResourceSelector{
|
||||
IncludedNamespaces: res.IncludedNamespaces,
|
||||
ExcludedNamespaces: res.ExcludedNamespaces,
|
||||
IncludedResources: res.IncludedResources,
|
||||
|
@ -85,7 +85,7 @@ func (c *RestoreItemActionGRPCClient) AppliesTo() (restore.ResourceSelector, err
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (c *RestoreItemActionGRPCClient) Execute(input *restore.RestoreItemActionExecuteInput) (*restore.RestoreItemActionExecuteOutput, error) {
|
||||
func (c *RestoreItemActionGRPCClient) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
itemJSON, err := json.Marshal(input.Item.UnstructuredContent())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -123,7 +123,7 @@ func (c *RestoreItemActionGRPCClient) Execute(input *restore.RestoreItemActionEx
|
|||
warning = errors.New(res.Warning)
|
||||
}
|
||||
|
||||
return &restore.RestoreItemActionExecuteOutput{
|
||||
return &velero.RestoreItemActionExecuteOutput{
|
||||
UpdatedItem: &updatedItem,
|
||||
Warning: warning,
|
||||
}, nil
|
||||
|
@ -145,13 +145,13 @@ type RestoreItemActionGRPCServer struct {
|
|||
mux *serverMux
|
||||
}
|
||||
|
||||
func (s *RestoreItemActionGRPCServer) getImpl(name string) (restore.ItemAction, error) {
|
||||
func (s *RestoreItemActionGRPCServer) getImpl(name string) (velero.RestoreItemAction, error) {
|
||||
impl, err := s.mux.getHandler(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
itemAction, ok := impl.(restore.ItemAction)
|
||||
itemAction, ok := impl.(velero.RestoreItemAction)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("%T is not a restore item action", impl)
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ func (s *RestoreItemActionGRPCServer) Execute(ctx context.Context, req *proto.Re
|
|||
return nil, err
|
||||
}
|
||||
|
||||
executeOutput, err := impl.Execute(&restore.RestoreItemActionExecuteInput{
|
||||
executeOutput, err := impl.Execute(&velero.RestoreItemActionExecuteInput{
|
||||
Item: &item,
|
||||
ItemFromBackup: &itemFromBackup,
|
||||
Restore: &restoreObj,
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2017 the Heptio Ark 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"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
)
|
||||
|
||||
// BackupItemAction is an actor that performs an operation on an individual item being backed up.
|
||||
type BackupItemAction interface {
|
||||
// AppliesTo returns information about which resources this action should be invoked for.
|
||||
// A BackupItemAction'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 backed up,
|
||||
// including mutating the item itself prior to backup. The item (unmodified or modified)
|
||||
// should be returned, along with an optional slice of ResourceIdentifiers specifying
|
||||
// additional related items that should be backed up.
|
||||
Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []ResourceIdentifier, error)
|
||||
}
|
||||
|
||||
// ResourceIdentifier describes a single item by its group, resource, namespace, and name.
|
||||
type ResourceIdentifier struct {
|
||||
schema.GroupResource
|
||||
Namespace string
|
||||
Name string
|
||||
}
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cloudprovider
|
||||
package velero
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cloudprovider
|
||||
package velero
|
||||
|
||||
import (
|
||||
"io"
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package restore
|
||||
package velero
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -22,10 +22,10 @@ import (
|
|||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
)
|
||||
|
||||
// ItemAction is an actor that performs an operation on an individual item being restored.
|
||||
type ItemAction interface {
|
||||
// RestoreItemAction is an actor that performs an operation on an individual item being restored.
|
||||
type RestoreItemAction interface {
|
||||
// AppliesTo returns information about which resources this action should be invoked for.
|
||||
// An ItemAction's Execute function will only be invoked on items that match the returned
|
||||
// A RestoreItemAction's Execute function will only be invoked on items that match the returned
|
||||
// selector. A zero-valued ResourceSelector matches all resources.
|
||||
AppliesTo() (ResourceSelector, error)
|
||||
|
||||
|
@ -57,42 +57,15 @@ type RestoreItemActionExecuteOutput struct {
|
|||
Warning error
|
||||
}
|
||||
|
||||
// NewRestoreItemActionExecuteOutput creates a new RestoreItemActionExecuteOutput
|
||||
func NewRestoreItemActionExecuteOutput(item runtime.Unstructured) *RestoreItemActionExecuteOutput {
|
||||
return &RestoreItemActionExecuteOutput{
|
||||
UpdatedItem: item,
|
||||
}
|
||||
}
|
||||
|
||||
// WithWarning returns a warning for RestoreItemActionExecuteOutput
|
||||
func (r *RestoreItemActionExecuteOutput) WithWarning(err error) *RestoreItemActionExecuteOutput {
|
||||
r.Warning = err
|
||||
return r
|
||||
}
|
||||
|
||||
// ResourceSelector is a collection of included/excluded namespaces,
|
||||
// included/excluded resources, and a label-selector that can be used
|
||||
// to match a set of items from a cluster.
|
||||
type ResourceSelector struct {
|
||||
// IncludedNamespaces is a slice of namespace names to match. All
|
||||
// namespaces in this slice, except those in ExcludedNamespaces,
|
||||
// will be matched. A nil/empty slice matches all namespaces.
|
||||
IncludedNamespaces []string
|
||||
// ExcludedNamespaces is a slice of namespace names to exclude.
|
||||
// All namespaces in IncludedNamespaces, *except* those in
|
||||
// this slice, will be matched.
|
||||
ExcludedNamespaces []string
|
||||
// IncludedResources is a slice of resources to match. Resources
|
||||
// may be specified as full names (e.g. "services") or abbreviations
|
||||
// (e.g. "svc"). All resources in this slice, except those in
|
||||
// ExcludedResources, will be matched. A nil/empty slice matches
|
||||
// all resources.
|
||||
IncludedResources []string
|
||||
// ExcludedResources is a slice of resources to exclude.
|
||||
// Resources may be specified as full names (e.g. "services") or
|
||||
// abbreviations (e.g. "svc"). All resources in IncludedResources,
|
||||
// *except* those in this slice, will be matched.
|
||||
ExcludedResources []string
|
||||
// LabelSelector is a string representation of a selector to apply
|
||||
// when matching resources. See "k8s.io/apimachinery/pkg/labels".Parse()
|
||||
// for details on syntax.
|
||||
LabelSelector string
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2017 the Heptio Ark contributors.
|
||||
Copyright 2019 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,35 +14,11 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package backup
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
)
|
||||
|
||||
// ItemAction is an actor that performs an operation on an individual item being backed up.
|
||||
type ItemAction interface {
|
||||
// AppliesTo returns information about which resources this action should be invoked for.
|
||||
// An ItemAction'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 backed up,
|
||||
// including mutating the item itself prior to backup. The item (unmodified or modified)
|
||||
// should be returned, along with an optional slice of ResourceIdentifiers specifying
|
||||
// additional related items that should be backed up.
|
||||
Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []ResourceIdentifier, error)
|
||||
}
|
||||
|
||||
// ResourceIdentifier describes a single item by its group, resource, namespace, and name.
|
||||
type ResourceIdentifier struct {
|
||||
schema.GroupResource
|
||||
Namespace string
|
||||
Name string
|
||||
}
|
||||
// Package velero contains the interfaces necessary to implement
|
||||
// all of the Velero plugins. Users create their own binary containing
|
||||
// implementations of the plugin kinds in this package. Multiple
|
||||
// plugins of any type can be implemented.
|
||||
package velero
|
||||
|
||||
// ResourceSelector is a collection of included/excluded namespaces,
|
||||
// included/excluded resources, and a label-selector that can be used
|
|
@ -22,23 +22,25 @@ import (
|
|||
batchv1api "k8s.io/api/batch/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
type jobAction struct {
|
||||
type JobAction struct {
|
||||
logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
func NewJobAction(logger logrus.FieldLogger) ItemAction {
|
||||
return &jobAction{logger: logger}
|
||||
func NewJobAction(logger logrus.FieldLogger) *JobAction {
|
||||
return &JobAction{logger: logger}
|
||||
}
|
||||
|
||||
func (a *jobAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (a *JobAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"jobs"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *jobAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItemActionExecuteOutput, error) {
|
||||
func (a *JobAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
job := new(batchv1api.Job)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(input.Item.UnstructuredContent(), job); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
|
@ -54,5 +56,5 @@ func (a *jobAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItemA
|
|||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
return velero.NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
||||
|
@ -137,7 +138,7 @@ func TestJobActionExecute(t *testing.T) {
|
|||
unstructuredJob, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&test.obj)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := action.Execute(&RestoreItemActionExecuteInput{
|
||||
res, err := action.Execute(&velero.RestoreItemActionExecuteInput{
|
||||
Item: &unstructured.Unstructured{Object: unstructuredJob},
|
||||
ItemFromBackup: &unstructured.Unstructured{Object: unstructuredJob},
|
||||
Restore: nil,
|
||||
|
|
|
@ -16,8 +16,11 @@ limitations under the License.
|
|||
// Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||
package mocks
|
||||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
import restore "github.com/heptio/velero/pkg/restore"
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
// ItemAction is an autogenerated mock type for the ItemAction type
|
||||
type ItemAction struct {
|
||||
|
@ -25,14 +28,14 @@ type ItemAction struct {
|
|||
}
|
||||
|
||||
// AppliesTo provides a mock function with given fields:
|
||||
func (_m *ItemAction) AppliesTo() (restore.ResourceSelector, error) {
|
||||
func (_m *ItemAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 restore.ResourceSelector
|
||||
if rf, ok := ret.Get(0).(func() restore.ResourceSelector); ok {
|
||||
var r0 velero.ResourceSelector
|
||||
if rf, ok := ret.Get(0).(func() velero.ResourceSelector); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(restore.ResourceSelector)
|
||||
r0 = ret.Get(0).(velero.ResourceSelector)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
|
@ -46,20 +49,20 @@ func (_m *ItemAction) AppliesTo() (restore.ResourceSelector, error) {
|
|||
}
|
||||
|
||||
// Execute provides a mock function with given fields: input
|
||||
func (_m *ItemAction) Execute(input *restore.RestoreItemActionExecuteInput) (*restore.RestoreItemActionExecuteOutput, error) {
|
||||
func (_m *ItemAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
ret := _m.Called(input)
|
||||
|
||||
var r0 *restore.RestoreItemActionExecuteOutput
|
||||
if rf, ok := ret.Get(0).(func(*restore.RestoreItemActionExecuteInput) *restore.RestoreItemActionExecuteOutput); ok {
|
||||
var r0 *velero.RestoreItemActionExecuteOutput
|
||||
if rf, ok := ret.Get(0).(func(*velero.RestoreItemActionExecuteInput) *velero.RestoreItemActionExecuteOutput); ok {
|
||||
r0 = rf(input)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*restore.RestoreItemActionExecuteOutput)
|
||||
r0 = ret.Get(0).(*velero.RestoreItemActionExecuteOutput)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*restore.RestoreItemActionExecuteInput) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(*velero.RestoreItemActionExecuteInput) error); ok {
|
||||
r1 = rf(input)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
|
|
|
@ -24,23 +24,25 @@ import (
|
|||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
type podAction struct {
|
||||
type PodAction struct {
|
||||
logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
func NewPodAction(logger logrus.FieldLogger) ItemAction {
|
||||
return &podAction{logger: logger}
|
||||
func NewPodAction(logger logrus.FieldLogger) *PodAction {
|
||||
return &PodAction{logger: logger}
|
||||
}
|
||||
|
||||
func (a *podAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (a *PodAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"pods"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *podAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItemActionExecuteOutput, error) {
|
||||
func (a *PodAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
pod := new(v1.Pod)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(input.Item.UnstructuredContent(), pod); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
|
@ -84,5 +86,5 @@ func (a *podAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItemA
|
|||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
return velero.NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
||||
|
@ -197,7 +198,7 @@ func TestPodActionExecute(t *testing.T) {
|
|||
unstructuredPod, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&test.obj)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := action.Execute(&RestoreItemActionExecuteInput{
|
||||
res, err := action.Execute(&velero.RestoreItemActionExecuteInput{
|
||||
Item: &unstructured.Unstructured{Object: unstructuredPod},
|
||||
ItemFromBackup: &unstructured.Unstructured{Object: unstructuredPod},
|
||||
Restore: nil,
|
||||
|
|
|
@ -26,10 +26,10 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
cloudprovidermocks "github.com/heptio/velero/pkg/cloudprovider/mocks"
|
||||
"github.com/heptio/velero/pkg/generated/clientset/versioned/fake"
|
||||
informers "github.com/heptio/velero/pkg/generated/informers/externalversions"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
"github.com/heptio/velero/pkg/volume"
|
||||
)
|
||||
|
@ -230,7 +230,7 @@ func TestExecutePVAction_SnapshotRestores(t *testing.T) {
|
|||
t.Run(tc.name, func(t *testing.T) {
|
||||
var (
|
||||
blockStore = new(cloudprovidermocks.BlockStore)
|
||||
blockStoreGetter = providerToBlockStoreMap(map[string]cloudprovider.BlockStore{
|
||||
blockStoreGetter = providerToBlockStoreMap(map[string]velero.BlockStore{
|
||||
tc.expectedProvider: blockStore,
|
||||
})
|
||||
locationsInformer = informers.NewSharedInformerFactory(fake.NewSimpleClientset(), 0).Velero().V1().VolumeSnapshotLocations()
|
||||
|
@ -260,9 +260,9 @@ func TestExecutePVAction_SnapshotRestores(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type providerToBlockStoreMap map[string]cloudprovider.BlockStore
|
||||
type providerToBlockStoreMap map[string]velero.BlockStore
|
||||
|
||||
func (g providerToBlockStoreMap) GetBlockStore(provider string) (cloudprovider.BlockStore, error) {
|
||||
func (g providerToBlockStoreMap) GetBlockStore(provider string) (velero.BlockStore, error) {
|
||||
if bs, ok := g[provider]; !ok {
|
||||
return nil, errors.New("block store not found for provider")
|
||||
} else {
|
||||
|
|
|
@ -26,17 +26,18 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/buildinfo"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/restic"
|
||||
"github.com/heptio/velero/pkg/util/kube"
|
||||
)
|
||||
|
||||
type resticRestoreAction struct {
|
||||
type ResticRestoreAction struct {
|
||||
logger logrus.FieldLogger
|
||||
initContainerImage string
|
||||
}
|
||||
|
||||
func NewResticRestoreAction(logger logrus.FieldLogger) ItemAction {
|
||||
return &resticRestoreAction{
|
||||
func NewResticRestoreAction(logger logrus.FieldLogger) *ResticRestoreAction {
|
||||
return &ResticRestoreAction{
|
||||
logger: logger,
|
||||
initContainerImage: initContainerImage(),
|
||||
}
|
||||
|
@ -52,15 +53,15 @@ func initContainerImage() string {
|
|||
return fmt.Sprintf("gcr.io/heptio-images/velero-restic-restore-helper:%s", tag)
|
||||
}
|
||||
|
||||
func (a *resticRestoreAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (a *ResticRestoreAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"pods"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *resticRestoreAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItemActionExecuteOutput, error) {
|
||||
a.logger.Info("Executing resticRestoreAction")
|
||||
defer a.logger.Info("Done executing resticRestoreAction")
|
||||
func (a *ResticRestoreAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
a.logger.Info("Executing ResticRestoreAction")
|
||||
defer a.logger.Info("Done executing ResticRestoreAction")
|
||||
|
||||
var pod corev1.Pod
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(input.Item.UnstructuredContent(), &pod); err != nil {
|
||||
|
@ -72,7 +73,7 @@ func (a *resticRestoreAction) Execute(input *RestoreItemActionExecuteInput) (*Re
|
|||
volumeSnapshots := restic.GetPodSnapshotAnnotations(&pod)
|
||||
if len(volumeSnapshots) == 0 {
|
||||
log.Debug("No restic snapshot ID annotations found")
|
||||
return NewRestoreItemActionExecuteOutput(input.Item), nil
|
||||
return velero.NewRestoreItemActionExecuteOutput(input.Item), nil
|
||||
}
|
||||
|
||||
log.Info("Restic snapshot ID annotations found")
|
||||
|
@ -120,5 +121,5 @@ func (a *resticRestoreAction) Execute(input *RestoreItemActionExecuteInput) (*Re
|
|||
return nil, errors.Wrap(err, "unable to convert pod to runtime.Unstructured")
|
||||
}
|
||||
|
||||
return NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
return velero.NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
}
|
||||
|
|
|
@ -44,10 +44,10 @@ import (
|
|||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/client"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/discovery"
|
||||
listers "github.com/heptio/velero/pkg/generated/listers/velero/v1"
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/restic"
|
||||
"github.com/heptio/velero/pkg/util/collections"
|
||||
"github.com/heptio/velero/pkg/util/filesystem"
|
||||
|
@ -57,7 +57,7 @@ import (
|
|||
)
|
||||
|
||||
type BlockStoreGetter interface {
|
||||
GetBlockStore(name string) (cloudprovider.BlockStore, error)
|
||||
GetBlockStore(name string) (velero.BlockStore, error)
|
||||
}
|
||||
|
||||
// Restorer knows how to restore a backup.
|
||||
|
@ -68,7 +68,7 @@ type Restorer interface {
|
|||
backup *api.Backup,
|
||||
volumeSnapshots []*volume.Snapshot,
|
||||
backupReader io.Reader,
|
||||
actions []ItemAction,
|
||||
actions []velero.RestoreItemAction,
|
||||
snapshotLocationLister listers.VolumeSnapshotLocationLister,
|
||||
blockStoreGetter BlockStoreGetter,
|
||||
) (api.RestoreResult, api.RestoreResult)
|
||||
|
@ -178,7 +178,7 @@ func (kr *kubernetesRestorer) Restore(
|
|||
backup *api.Backup,
|
||||
volumeSnapshots []*volume.Snapshot,
|
||||
backupReader io.Reader,
|
||||
actions []ItemAction,
|
||||
actions []velero.RestoreItemAction,
|
||||
snapshotLocationLister listers.VolumeSnapshotLocationLister,
|
||||
blockStoreGetter BlockStoreGetter,
|
||||
) (api.RestoreResult, api.RestoreResult) {
|
||||
|
@ -287,14 +287,14 @@ func getResourceIncludesExcludes(helper discovery.Helper, includes, excludes []s
|
|||
}
|
||||
|
||||
type resolvedAction struct {
|
||||
ItemAction
|
||||
velero.RestoreItemAction
|
||||
|
||||
resourceIncludesExcludes *collections.IncludesExcludes
|
||||
namespaceIncludesExcludes *collections.IncludesExcludes
|
||||
selector labels.Selector
|
||||
}
|
||||
|
||||
func resolveActions(actions []ItemAction, helper discovery.Helper) ([]resolvedAction, error) {
|
||||
func resolveActions(actions []velero.RestoreItemAction, helper discovery.Helper) ([]resolvedAction, error) {
|
||||
var resolved []resolvedAction
|
||||
|
||||
for _, action := range actions {
|
||||
|
@ -314,7 +314,7 @@ func resolveActions(actions []ItemAction, helper discovery.Helper) ([]resolvedAc
|
|||
}
|
||||
|
||||
res := resolvedAction{
|
||||
ItemAction: action,
|
||||
RestoreItemAction: action,
|
||||
resourceIncludesExcludes: resources,
|
||||
namespaceIncludesExcludes: namespaces,
|
||||
selector: selector,
|
||||
|
@ -834,7 +834,7 @@ func (ctx *context) restoreResource(resource, namespace, resourcePath string) (a
|
|||
|
||||
ctx.log.Infof("Executing item action for %v", &groupResource)
|
||||
|
||||
executeOutput, err := action.Execute(&RestoreItemActionExecuteInput{
|
||||
executeOutput, err := action.Execute(&velero.RestoreItemActionExecuteInput{
|
||||
Item: obj,
|
||||
ItemFromBackup: itemFromBackup,
|
||||
Restore: ctx.restore,
|
||||
|
|
|
@ -39,10 +39,10 @@ import (
|
|||
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
|
||||
api "github.com/heptio/velero/pkg/apis/velero/v1"
|
||||
"github.com/heptio/velero/pkg/cloudprovider"
|
||||
"github.com/heptio/velero/pkg/generated/clientset/versioned/fake"
|
||||
informers "github.com/heptio/velero/pkg/generated/informers/externalversions"
|
||||
"github.com/heptio/velero/pkg/kuberesource"
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/util/collections"
|
||||
"github.com/heptio/velero/pkg/util/logging"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
|
@ -462,7 +462,7 @@ func TestRestoreResourceForNamespace(t *testing.T) {
|
|||
fileSystem: velerotest.NewFakeFileSystem().WithFile("configmaps/cm-1.json", newTestConfigMap().ToJSON()),
|
||||
actions: []resolvedAction{
|
||||
{
|
||||
ItemAction: newFakeAction("configmaps"),
|
||||
RestoreItemAction: newFakeAction("configmaps"),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes().Includes("configmaps"),
|
||||
namespaceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
selector: labels.Everything(),
|
||||
|
@ -478,7 +478,7 @@ func TestRestoreResourceForNamespace(t *testing.T) {
|
|||
fileSystem: velerotest.NewFakeFileSystem().WithFile("configmaps/cm-1.json", newTestConfigMap().ToJSON()),
|
||||
actions: []resolvedAction{
|
||||
{
|
||||
ItemAction: newFakeAction("foo-resource"),
|
||||
RestoreItemAction: newFakeAction("foo-resource"),
|
||||
resourceIncludesExcludes: collections.NewIncludesExcludes().Includes("foo-resource"),
|
||||
namespaceIncludesExcludes: collections.NewIncludesExcludes(),
|
||||
selector: labels.Everything(),
|
||||
|
@ -1805,7 +1805,7 @@ type fakeBlockStoreGetter struct {
|
|||
volumeID string
|
||||
}
|
||||
|
||||
func (r *fakeBlockStoreGetter) GetBlockStore(provider string) (cloudprovider.BlockStore, error) {
|
||||
func (r *fakeBlockStoreGetter) GetBlockStore(provider string) (velero.BlockStore, error) {
|
||||
if r.fakeBlockStore == nil {
|
||||
r.fakeBlockStore = &velerotest.FakeBlockStore{
|
||||
RestorableVolumes: r.volumeMap,
|
||||
|
@ -1819,13 +1819,13 @@ func newFakeAction(resource string) *fakeAction {
|
|||
return &fakeAction{resource}
|
||||
}
|
||||
|
||||
func (r *fakeAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (r *fakeAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{r.resource},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *fakeAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItemActionExecuteOutput, error) {
|
||||
func (r *fakeAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
labels, found, err := unstructured.NestedMap(input.Item.UnstructuredContent(), "metadata", "labels")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1851,7 +1851,7 @@ func (r *fakeAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItem
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return NewRestoreItemActionExecuteOutput(res), nil
|
||||
return velero.NewRestoreItemActionExecuteOutput(res), nil
|
||||
}
|
||||
|
||||
type fakeNamespaceClient struct {
|
||||
|
|
|
@ -25,26 +25,27 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/util/kube"
|
||||
)
|
||||
|
||||
type serviceAccountAction struct {
|
||||
type ServiceAccountAction struct {
|
||||
logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
func NewServiceAccountAction(logger logrus.FieldLogger) ItemAction {
|
||||
return &serviceAccountAction{logger: logger}
|
||||
func NewServiceAccountAction(logger logrus.FieldLogger) *ServiceAccountAction {
|
||||
return &ServiceAccountAction{logger: logger}
|
||||
}
|
||||
|
||||
func (a *serviceAccountAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (a *ServiceAccountAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"serviceaccounts"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *serviceAccountAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItemActionExecuteOutput, error) {
|
||||
a.logger.Info("Executing serviceAccountAction")
|
||||
defer a.logger.Info("Done executing serviceAccountAction")
|
||||
func (a *ServiceAccountAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
a.logger.Info("Executing ServiceAccountAction")
|
||||
defer a.logger.Info("Done executing ServiceAccountAction")
|
||||
|
||||
var serviceAccount corev1.ServiceAccount
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(input.Item.UnstructuredContent(), &serviceAccount); err != nil {
|
||||
|
@ -74,5 +75,5 @@ func (a *serviceAccountAction) Execute(input *RestoreItemActionExecuteInput) (*R
|
|||
return nil, errors.Wrap(err, "unable to convert serviceaccount to runtime.Unstructured")
|
||||
}
|
||||
|
||||
return NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
return velero.NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
"github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
||||
|
@ -34,7 +35,7 @@ func TestServiceAccountActionAppliesTo(t *testing.T) {
|
|||
action := NewServiceAccountAction(test.NewLogger())
|
||||
actual, err := action.AppliesTo()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, ResourceSelector{IncludedResources: []string{"serviceaccounts"}}, actual)
|
||||
assert.Equal(t, velero.ResourceSelector{IncludedResources: []string{"serviceaccounts"}}, actual)
|
||||
}
|
||||
|
||||
func TestServiceAccountActionExecute(t *testing.T) {
|
||||
|
@ -89,7 +90,7 @@ func TestServiceAccountActionExecute(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
action := NewServiceAccountAction(test.NewLogger())
|
||||
res, err := action.Execute(&RestoreItemActionExecuteInput{
|
||||
res, err := action.Execute(&velero.RestoreItemActionExecuteInput{
|
||||
Item: &unstructured.Unstructured{Object: saUnstructured},
|
||||
ItemFromBackup: &unstructured.Unstructured{Object: saUnstructured},
|
||||
Restore: nil,
|
||||
|
|
|
@ -25,25 +25,27 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
)
|
||||
|
||||
const annotationLastAppliedConfig = "kubectl.kubernetes.io/last-applied-configuration"
|
||||
|
||||
type serviceAction struct {
|
||||
type ServiceAction struct {
|
||||
log logrus.FieldLogger
|
||||
}
|
||||
|
||||
func NewServiceAction(logger logrus.FieldLogger) ItemAction {
|
||||
return &serviceAction{log: logger}
|
||||
func NewServiceAction(logger logrus.FieldLogger) *ServiceAction {
|
||||
return &ServiceAction{log: logger}
|
||||
}
|
||||
|
||||
func (a *serviceAction) AppliesTo() (ResourceSelector, error) {
|
||||
return ResourceSelector{
|
||||
func (a *ServiceAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"services"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *serviceAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreItemActionExecuteOutput, error) {
|
||||
func (a *ServiceAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
service := new(corev1api.Service)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(input.Item.UnstructuredContent(), service); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
|
@ -62,7 +64,7 @@ func (a *serviceAction) Execute(input *RestoreItemActionExecuteInput) (*RestoreI
|
|||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
return velero.NewRestoreItemActionExecuteOutput(&unstructured.Unstructured{Object: res}), nil
|
||||
}
|
||||
|
||||
func deleteNodePorts(service *corev1api.Service) error {
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/heptio/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/heptio/velero/pkg/util/test"
|
||||
)
|
||||
|
||||
|
@ -274,7 +275,7 @@ func TestServiceActionExecute(t *testing.T) {
|
|||
unstructuredSvc, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&test.obj)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := action.Execute(&RestoreItemActionExecuteInput{
|
||||
res, err := action.Execute(&velero.RestoreItemActionExecuteInput{
|
||||
Item: &unstructured.Unstructured{Object: unstructuredSvc},
|
||||
ItemFromBackup: &unstructured.Unstructured{Object: unstructuredSvc},
|
||||
Restore: nil,
|
||||
|
|
Loading…
Reference in New Issue