remove SnapshotService, replace with direct BlockStore usage
Signed-off-by: Steve Kriss <steve@heptio.com>pull/715/head
parent
430ec2451a
commit
1c26fbde32
|
@ -55,7 +55,7 @@ type kubernetesBackupper struct {
|
||||||
discoveryHelper discovery.Helper
|
discoveryHelper discovery.Helper
|
||||||
podCommandExecutor podexec.PodCommandExecutor
|
podCommandExecutor podexec.PodCommandExecutor
|
||||||
groupBackupperFactory groupBackupperFactory
|
groupBackupperFactory groupBackupperFactory
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
resticBackupperFactory restic.BackupperFactory
|
resticBackupperFactory restic.BackupperFactory
|
||||||
resticTimeout time.Duration
|
resticTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ func NewKubernetesBackupper(
|
||||||
discoveryHelper discovery.Helper,
|
discoveryHelper discovery.Helper,
|
||||||
dynamicFactory client.DynamicFactory,
|
dynamicFactory client.DynamicFactory,
|
||||||
podCommandExecutor podexec.PodCommandExecutor,
|
podCommandExecutor podexec.PodCommandExecutor,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupperFactory restic.BackupperFactory,
|
resticBackupperFactory restic.BackupperFactory,
|
||||||
resticTimeout time.Duration,
|
resticTimeout time.Duration,
|
||||||
) (Backupper, error) {
|
) (Backupper, error) {
|
||||||
|
@ -102,7 +102,7 @@ func NewKubernetesBackupper(
|
||||||
dynamicFactory: dynamicFactory,
|
dynamicFactory: dynamicFactory,
|
||||||
podCommandExecutor: podCommandExecutor,
|
podCommandExecutor: podCommandExecutor,
|
||||||
groupBackupperFactory: &defaultGroupBackupperFactory{},
|
groupBackupperFactory: &defaultGroupBackupperFactory{},
|
||||||
snapshotService: snapshotService,
|
blockStore: blockStore,
|
||||||
resticBackupperFactory: resticBackupperFactory,
|
resticBackupperFactory: resticBackupperFactory,
|
||||||
resticTimeout: resticTimeout,
|
resticTimeout: resticTimeout,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -276,7 +276,7 @@ func (kb *kubernetesBackupper) Backup(logger logrus.FieldLogger, backup *api.Bac
|
||||||
kb.podCommandExecutor,
|
kb.podCommandExecutor,
|
||||||
tw,
|
tw,
|
||||||
resourceHooks,
|
resourceHooks,
|
||||||
kb.snapshotService,
|
kb.blockStore,
|
||||||
resticBackupper,
|
resticBackupper,
|
||||||
newPVCSnapshotTracker(),
|
newPVCSnapshotTracker(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -652,7 +652,7 @@ func (f *mockGroupBackupperFactory) newGroupBackupper(
|
||||||
podCommandExecutor podexec.PodCommandExecutor,
|
podCommandExecutor podexec.PodCommandExecutor,
|
||||||
tarWriter tarWriter,
|
tarWriter tarWriter,
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) groupBackupper {
|
) groupBackupper {
|
||||||
|
@ -669,7 +669,7 @@ func (f *mockGroupBackupperFactory) newGroupBackupper(
|
||||||
podCommandExecutor,
|
podCommandExecutor,
|
||||||
tarWriter,
|
tarWriter,
|
||||||
resourceHooks,
|
resourceHooks,
|
||||||
snapshotService,
|
blockStore,
|
||||||
resticBackupper,
|
resticBackupper,
|
||||||
resticSnapshotTracker,
|
resticSnapshotTracker,
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,7 +49,7 @@ type groupBackupperFactory interface {
|
||||||
podCommandExecutor podexec.PodCommandExecutor,
|
podCommandExecutor podexec.PodCommandExecutor,
|
||||||
tarWriter tarWriter,
|
tarWriter tarWriter,
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) groupBackupper
|
) groupBackupper
|
||||||
|
@ -69,7 +69,7 @@ func (f *defaultGroupBackupperFactory) newGroupBackupper(
|
||||||
podCommandExecutor podexec.PodCommandExecutor,
|
podCommandExecutor podexec.PodCommandExecutor,
|
||||||
tarWriter tarWriter,
|
tarWriter tarWriter,
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) groupBackupper {
|
) groupBackupper {
|
||||||
|
@ -86,7 +86,7 @@ func (f *defaultGroupBackupperFactory) newGroupBackupper(
|
||||||
podCommandExecutor: podCommandExecutor,
|
podCommandExecutor: podCommandExecutor,
|
||||||
tarWriter: tarWriter,
|
tarWriter: tarWriter,
|
||||||
resourceHooks: resourceHooks,
|
resourceHooks: resourceHooks,
|
||||||
snapshotService: snapshotService,
|
blockStore: blockStore,
|
||||||
resticBackupper: resticBackupper,
|
resticBackupper: resticBackupper,
|
||||||
resticSnapshotTracker: resticSnapshotTracker,
|
resticSnapshotTracker: resticSnapshotTracker,
|
||||||
resourceBackupperFactory: &defaultResourceBackupperFactory{},
|
resourceBackupperFactory: &defaultResourceBackupperFactory{},
|
||||||
|
@ -109,7 +109,7 @@ type defaultGroupBackupper struct {
|
||||||
podCommandExecutor podexec.PodCommandExecutor
|
podCommandExecutor podexec.PodCommandExecutor
|
||||||
tarWriter tarWriter
|
tarWriter tarWriter
|
||||||
resourceHooks []resourceHook
|
resourceHooks []resourceHook
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
resticBackupper restic.Backupper
|
resticBackupper restic.Backupper
|
||||||
resticSnapshotTracker *pvcSnapshotTracker
|
resticSnapshotTracker *pvcSnapshotTracker
|
||||||
resourceBackupperFactory resourceBackupperFactory
|
resourceBackupperFactory resourceBackupperFactory
|
||||||
|
@ -133,7 +133,7 @@ func (gb *defaultGroupBackupper) backupGroup(group *metav1.APIResourceList) erro
|
||||||
gb.podCommandExecutor,
|
gb.podCommandExecutor,
|
||||||
gb.tarWriter,
|
gb.tarWriter,
|
||||||
gb.resourceHooks,
|
gb.resourceHooks,
|
||||||
gb.snapshotService,
|
gb.blockStore,
|
||||||
gb.resticBackupper,
|
gb.resticBackupper,
|
||||||
gb.resticSnapshotTracker,
|
gb.resticSnapshotTracker,
|
||||||
)
|
)
|
||||||
|
|
|
@ -161,7 +161,7 @@ func (rbf *mockResourceBackupperFactory) newResourceBackupper(
|
||||||
podCommandExecutor podexec.PodCommandExecutor,
|
podCommandExecutor podexec.PodCommandExecutor,
|
||||||
tarWriter tarWriter,
|
tarWriter tarWriter,
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) resourceBackupper {
|
) resourceBackupper {
|
||||||
|
@ -178,7 +178,7 @@ func (rbf *mockResourceBackupperFactory) newResourceBackupper(
|
||||||
podCommandExecutor,
|
podCommandExecutor,
|
||||||
tarWriter,
|
tarWriter,
|
||||||
resourceHooks,
|
resourceHooks,
|
||||||
snapshotService,
|
blockStore,
|
||||||
resticBackupper,
|
resticBackupper,
|
||||||
resticSnapshotTracker,
|
resticSnapshotTracker,
|
||||||
)
|
)
|
||||||
|
|
|
@ -54,7 +54,7 @@ type itemBackupperFactory interface {
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
dynamicFactory client.DynamicFactory,
|
dynamicFactory client.DynamicFactory,
|
||||||
discoveryHelper discovery.Helper,
|
discoveryHelper discovery.Helper,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) ItemBackupper
|
) ItemBackupper
|
||||||
|
@ -72,7 +72,7 @@ func (f *defaultItemBackupperFactory) newItemBackupper(
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
dynamicFactory client.DynamicFactory,
|
dynamicFactory client.DynamicFactory,
|
||||||
discoveryHelper discovery.Helper,
|
discoveryHelper discovery.Helper,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) ItemBackupper {
|
) ItemBackupper {
|
||||||
|
@ -86,7 +86,7 @@ func (f *defaultItemBackupperFactory) newItemBackupper(
|
||||||
resourceHooks: resourceHooks,
|
resourceHooks: resourceHooks,
|
||||||
dynamicFactory: dynamicFactory,
|
dynamicFactory: dynamicFactory,
|
||||||
discoveryHelper: discoveryHelper,
|
discoveryHelper: discoveryHelper,
|
||||||
snapshotService: snapshotService,
|
blockStore: blockStore,
|
||||||
itemHookHandler: &defaultItemHookHandler{
|
itemHookHandler: &defaultItemHookHandler{
|
||||||
podCommandExecutor: podCommandExecutor,
|
podCommandExecutor: podCommandExecutor,
|
||||||
},
|
},
|
||||||
|
@ -114,7 +114,7 @@ type defaultItemBackupper struct {
|
||||||
resourceHooks []resourceHook
|
resourceHooks []resourceHook
|
||||||
dynamicFactory client.DynamicFactory
|
dynamicFactory client.DynamicFactory
|
||||||
discoveryHelper discovery.Helper
|
discoveryHelper discovery.Helper
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
resticBackupper restic.Backupper
|
resticBackupper restic.Backupper
|
||||||
resticSnapshotTracker *pvcSnapshotTracker
|
resticSnapshotTracker *pvcSnapshotTracker
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ func (ib *defaultItemBackupper) backupItem(logger logrus.FieldLogger, obj runtim
|
||||||
obj = updatedObj
|
obj = updatedObj
|
||||||
|
|
||||||
if groupResource == kuberesource.PersistentVolumes {
|
if groupResource == kuberesource.PersistentVolumes {
|
||||||
if ib.snapshotService == nil {
|
if ib.blockStore == nil {
|
||||||
log.Debug("Skipping Persistent Volume snapshot because they're not enabled.")
|
log.Debug("Skipping Persistent Volume snapshot because they're not enabled.")
|
||||||
} else if err := ib.takePVSnapshot(obj, ib.backup, log); err != nil {
|
} else if err := ib.takePVSnapshot(obj, ib.backup, log); err != nil {
|
||||||
backupErrs = append(backupErrs, err)
|
backupErrs = append(backupErrs, err)
|
||||||
|
@ -399,7 +399,7 @@ func (ib *defaultItemBackupper) takePVSnapshot(obj runtime.Unstructured, backup
|
||||||
log.Infof("label %q is not present on PersistentVolume", zoneLabel)
|
log.Infof("label %q is not present on PersistentVolume", zoneLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
volumeID, err := ib.snapshotService.GetVolumeID(obj)
|
volumeID, err := ib.blockStore.GetVolumeID(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error getting volume ID for PersistentVolume")
|
return errors.Wrapf(err, "error getting volume ID for PersistentVolume")
|
||||||
}
|
}
|
||||||
|
@ -416,14 +416,14 @@ func (ib *defaultItemBackupper) takePVSnapshot(obj runtime.Unstructured, backup
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Snapshotting PersistentVolume")
|
log.Info("Snapshotting PersistentVolume")
|
||||||
snapshotID, err := ib.snapshotService.CreateSnapshot(volumeID, pvFailureDomainZone, tags)
|
snapshotID, err := ib.blockStore.CreateSnapshot(volumeID, pvFailureDomainZone, tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// log+error on purpose - log goes to the per-backup log file, error goes to the backup
|
// log+error on purpose - log goes to the per-backup log file, error goes to the backup
|
||||||
log.WithError(err).Error("error creating snapshot")
|
log.WithError(err).Error("error creating snapshot")
|
||||||
return errors.WithMessage(err, "error creating snapshot")
|
return errors.WithMessage(err, "error creating snapshot")
|
||||||
}
|
}
|
||||||
|
|
||||||
volumeType, iops, err := ib.snapshotService.GetVolumeInfo(volumeID, pvFailureDomainZone)
|
volumeType, iops, err := ib.blockStore.GetVolumeInfo(volumeID, pvFailureDomainZone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("error getting volume info")
|
log.WithError(err).Error("error getting volume info")
|
||||||
return errors.WithMessage(err, "error getting volume info")
|
return errors.WithMessage(err, "error getting volume info")
|
||||||
|
|
|
@ -277,7 +277,7 @@ func TestBackupItemNoSkips(t *testing.T) {
|
||||||
additionalItemError: errors.New("foo"),
|
additionalItemError: errors.New("foo"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "takePVSnapshot is not invoked for PVs when snapshotService == nil",
|
name: "takePVSnapshot is not invoked for PVs when blockStore == nil",
|
||||||
namespaceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
|
namespaceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
|
||||||
item: `{"apiVersion": "v1", "kind": "PersistentVolume", "metadata": {"name": "mypv", "labels": {"failure-domain.beta.kubernetes.io/zone": "us-east-1c"}}, "spec": {"awsElasticBlockStore": {"volumeID": "aws://us-east-1c/vol-abc123"}}}`,
|
item: `{"apiVersion": "v1", "kind": "PersistentVolume", "metadata": {"name": "mypv", "labels": {"failure-domain.beta.kubernetes.io/zone": "us-east-1c"}}, "spec": {"awsElasticBlockStore": {"volumeID": "aws://us-east-1c/vol-abc123"}}}`,
|
||||||
expectError: false,
|
expectError: false,
|
||||||
|
@ -286,7 +286,7 @@ func TestBackupItemNoSkips(t *testing.T) {
|
||||||
groupResource: "persistentvolumes",
|
groupResource: "persistentvolumes",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "takePVSnapshot is invoked for PVs when snapshotService != nil",
|
name: "takePVSnapshot is invoked for PVs when blockStore != nil",
|
||||||
namespaceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
|
namespaceIncludesExcludes: collections.NewIncludesExcludes().Includes("*"),
|
||||||
item: `{"apiVersion": "v1", "kind": "PersistentVolume", "metadata": {"name": "mypv", "labels": {"failure-domain.beta.kubernetes.io/zone": "us-east-1c"}}, "spec": {"awsElasticBlockStore": {"volumeID": "aws://us-east-1c/vol-abc123"}}}`,
|
item: `{"apiVersion": "v1", "kind": "PersistentVolume", "metadata": {"name": "mypv", "labels": {"failure-domain.beta.kubernetes.io/zone": "us-east-1c"}}, "spec": {"awsElasticBlockStore": {"volumeID": "aws://us-east-1c/vol-abc123"}}}`,
|
||||||
expectError: false,
|
expectError: false,
|
||||||
|
@ -305,7 +305,7 @@ func TestBackupItemNoSkips(t *testing.T) {
|
||||||
expectExcluded: false,
|
expectExcluded: false,
|
||||||
expectedTarHeaderName: "resources/persistentvolumes/cluster/mypv.json",
|
expectedTarHeaderName: "resources/persistentvolumes/cluster/mypv.json",
|
||||||
groupResource: "persistentvolumes",
|
groupResource: "persistentvolumes",
|
||||||
// empty snapshottableVolumes causes a snapshotService to be created, but no
|
// empty snapshottableVolumes causes a blockStore to be created, but no
|
||||||
// snapshots are expected to be taken.
|
// snapshots are expected to be taken.
|
||||||
snapshottableVolumes: map[string]api.VolumeBackupInfo{},
|
snapshottableVolumes: map[string]api.VolumeBackupInfo{},
|
||||||
trackedPVCs: sets.NewString(key("pvc-ns", "pvc"), key("another-pvc-ns", "another-pvc")),
|
trackedPVCs: sets.NewString(key("pvc-ns", "pvc"), key("another-pvc-ns", "another-pvc")),
|
||||||
|
@ -419,14 +419,14 @@ func TestBackupItemNoSkips(t *testing.T) {
|
||||||
newPVCSnapshotTracker(),
|
newPVCSnapshotTracker(),
|
||||||
).(*defaultItemBackupper)
|
).(*defaultItemBackupper)
|
||||||
|
|
||||||
var snapshotService *arktest.FakeSnapshotService
|
var blockStore *arktest.FakeBlockStore
|
||||||
if test.snapshottableVolumes != nil {
|
if test.snapshottableVolumes != nil {
|
||||||
snapshotService = &arktest.FakeSnapshotService{
|
blockStore = &arktest.FakeBlockStore{
|
||||||
SnapshottableVolumes: test.snapshottableVolumes,
|
SnapshottableVolumes: test.snapshottableVolumes,
|
||||||
VolumeID: "vol-abc123",
|
VolumeID: "vol-abc123",
|
||||||
Error: test.snapshotError,
|
Error: test.snapshotError,
|
||||||
}
|
}
|
||||||
b.snapshotService = snapshotService
|
b.blockStore = blockStore
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.trackedPVCs != nil {
|
if test.trackedPVCs != nil {
|
||||||
|
@ -514,7 +514,7 @@ func TestBackupItemNoSkips(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if test.snapshottableVolumes != nil {
|
if test.snapshottableVolumes != nil {
|
||||||
require.Equal(t, len(test.snapshottableVolumes), len(snapshotService.SnapshotsTaken))
|
require.Equal(t, len(test.snapshottableVolumes), len(blockStore.SnapshotsTaken))
|
||||||
|
|
||||||
var expectedBackups []api.VolumeBackupInfo
|
var expectedBackups []api.VolumeBackupInfo
|
||||||
for _, vbi := range test.snapshottableVolumes {
|
for _, vbi := range test.snapshottableVolumes {
|
||||||
|
@ -719,12 +719,12 @@ func TestTakePVSnapshot(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshotService := &arktest.FakeSnapshotService{
|
blockStore := &arktest.FakeBlockStore{
|
||||||
SnapshottableVolumes: test.volumeInfo,
|
SnapshottableVolumes: test.volumeInfo,
|
||||||
VolumeID: test.expectedVolumeID,
|
VolumeID: test.expectedVolumeID,
|
||||||
}
|
}
|
||||||
|
|
||||||
ib := &defaultItemBackupper{snapshotService: snapshotService}
|
ib := &defaultItemBackupper{blockStore: blockStore}
|
||||||
|
|
||||||
pv, err := arktest.GetAsMap(test.pv)
|
pv, err := arktest.GetAsMap(test.pv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -754,12 +754,12 @@ func TestTakePVSnapshot(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// we should have one snapshot taken exactly
|
// we should have one snapshot taken exactly
|
||||||
require.Equal(t, test.expectedSnapshotsTaken, snapshotService.SnapshotsTaken.Len())
|
require.Equal(t, test.expectedSnapshotsTaken, blockStore.SnapshotsTaken.Len())
|
||||||
|
|
||||||
if test.expectedSnapshotsTaken > 0 {
|
if test.expectedSnapshotsTaken > 0 {
|
||||||
// the snapshotID should be the one in the entry in snapshotService.SnapshottableVolumes
|
// the snapshotID should be the one in the entry in blockStore.SnapshottableVolumes
|
||||||
// for the volume we ran the test for
|
// for the volume we ran the test for
|
||||||
snapshotID, _ := snapshotService.SnapshotsTaken.PopAny()
|
snapshotID, _ := blockStore.SnapshotsTaken.PopAny()
|
||||||
|
|
||||||
expectedVolumeBackups["mypv"] = &v1.VolumeBackupInfo{
|
expectedVolumeBackups["mypv"] = &v1.VolumeBackupInfo{
|
||||||
SnapshotID: snapshotID,
|
SnapshotID: snapshotID,
|
||||||
|
|
|
@ -51,7 +51,7 @@ type resourceBackupperFactory interface {
|
||||||
podCommandExecutor podexec.PodCommandExecutor,
|
podCommandExecutor podexec.PodCommandExecutor,
|
||||||
tarWriter tarWriter,
|
tarWriter tarWriter,
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) resourceBackupper
|
) resourceBackupper
|
||||||
|
@ -72,7 +72,7 @@ func (f *defaultResourceBackupperFactory) newResourceBackupper(
|
||||||
podCommandExecutor podexec.PodCommandExecutor,
|
podCommandExecutor podexec.PodCommandExecutor,
|
||||||
tarWriter tarWriter,
|
tarWriter tarWriter,
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) resourceBackupper {
|
) resourceBackupper {
|
||||||
|
@ -89,7 +89,7 @@ func (f *defaultResourceBackupperFactory) newResourceBackupper(
|
||||||
podCommandExecutor: podCommandExecutor,
|
podCommandExecutor: podCommandExecutor,
|
||||||
tarWriter: tarWriter,
|
tarWriter: tarWriter,
|
||||||
resourceHooks: resourceHooks,
|
resourceHooks: resourceHooks,
|
||||||
snapshotService: snapshotService,
|
blockStore: blockStore,
|
||||||
resticBackupper: resticBackupper,
|
resticBackupper: resticBackupper,
|
||||||
resticSnapshotTracker: resticSnapshotTracker,
|
resticSnapshotTracker: resticSnapshotTracker,
|
||||||
itemBackupperFactory: &defaultItemBackupperFactory{},
|
itemBackupperFactory: &defaultItemBackupperFactory{},
|
||||||
|
@ -113,7 +113,7 @@ type defaultResourceBackupper struct {
|
||||||
podCommandExecutor podexec.PodCommandExecutor
|
podCommandExecutor podexec.PodCommandExecutor
|
||||||
tarWriter tarWriter
|
tarWriter tarWriter
|
||||||
resourceHooks []resourceHook
|
resourceHooks []resourceHook
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
resticBackupper restic.Backupper
|
resticBackupper restic.Backupper
|
||||||
resticSnapshotTracker *pvcSnapshotTracker
|
resticSnapshotTracker *pvcSnapshotTracker
|
||||||
itemBackupperFactory itemBackupperFactory
|
itemBackupperFactory itemBackupperFactory
|
||||||
|
@ -189,7 +189,7 @@ func (rb *defaultResourceBackupper) backupResource(
|
||||||
rb.resourceHooks,
|
rb.resourceHooks,
|
||||||
rb.dynamicFactory,
|
rb.dynamicFactory,
|
||||||
rb.discoveryHelper,
|
rb.discoveryHelper,
|
||||||
rb.snapshotService,
|
rb.blockStore,
|
||||||
rb.resticBackupper,
|
rb.resticBackupper,
|
||||||
rb.resticSnapshotTracker,
|
rb.resticSnapshotTracker,
|
||||||
)
|
)
|
||||||
|
|
|
@ -544,7 +544,6 @@ func TestBackupResourceOnlyIncludesSpecifiedNamespaces(t *testing.T) {
|
||||||
dynamicFactory: dynamicFactory,
|
dynamicFactory: dynamicFactory,
|
||||||
discoveryHelper: discoveryHelper,
|
discoveryHelper: discoveryHelper,
|
||||||
itemHookHandler: itemHookHandler,
|
itemHookHandler: itemHookHandler,
|
||||||
snapshotService: nil,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
itemBackupperFactory.On("newItemBackupper",
|
itemBackupperFactory.On("newItemBackupper",
|
||||||
|
@ -690,7 +689,7 @@ func (ibf *mockItemBackupperFactory) newItemBackupper(
|
||||||
resourceHooks []resourceHook,
|
resourceHooks []resourceHook,
|
||||||
dynamicFactory client.DynamicFactory,
|
dynamicFactory client.DynamicFactory,
|
||||||
discoveryHelper discovery.Helper,
|
discoveryHelper discovery.Helper,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resticBackupper restic.Backupper,
|
resticBackupper restic.Backupper,
|
||||||
resticSnapshotTracker *pvcSnapshotTracker,
|
resticSnapshotTracker *pvcSnapshotTracker,
|
||||||
) ItemBackupper {
|
) ItemBackupper {
|
||||||
|
@ -705,7 +704,7 @@ func (ibf *mockItemBackupperFactory) newItemBackupper(
|
||||||
resourceHooks,
|
resourceHooks,
|
||||||
dynamicFactory,
|
dynamicFactory,
|
||||||
discoveryHelper,
|
discoveryHelper,
|
||||||
snapshotService,
|
blockStore,
|
||||||
resticBackupper,
|
resticBackupper,
|
||||||
resticSnapshotTracker,
|
resticSnapshotTracker,
|
||||||
)
|
)
|
||||||
|
|
|
@ -141,15 +141,6 @@ func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, e
|
||||||
return volumeType, iops, nil
|
return volumeType, iops, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *blockStore) IsVolumeReady(volumeID, volumeAZ string) (ready bool, err error) {
|
|
||||||
volumeInfo, err := b.describeVolume(volumeID)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return *volumeInfo.State == ec2.VolumeStateAvailable, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *blockStore) describeVolume(volumeID string) (*ec2.Volume, error) {
|
func (b *blockStore) describeVolume(volumeID string) (*ec2.Volume, error) {
|
||||||
req := &ec2.DescribeVolumesInput{
|
req := &ec2.DescribeVolumesInput{
|
||||||
VolumeIds: []*string{&volumeID},
|
VolumeIds: []*string{&volumeID},
|
||||||
|
|
|
@ -183,19 +183,6 @@ func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, e
|
||||||
return string(res.AccountType), nil, nil
|
return string(res.AccountType), nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *blockStore) IsVolumeReady(volumeID, volumeAZ string) (ready bool, err error) {
|
|
||||||
res, err := b.disks.Get(b.resourceGroup, volumeID)
|
|
||||||
if err != nil {
|
|
||||||
return false, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.ProvisioningState == nil {
|
|
||||||
return false, errors.New("nil ProvisioningState returned from Get call")
|
|
||||||
}
|
|
||||||
|
|
||||||
return *res.ProvisioningState == "Succeeded", 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
|
// Lookup disk info for its Location
|
||||||
diskInfo, err := b.disks.Get(b.resourceGroup, volumeID)
|
diskInfo, err := b.disks.Get(b.resourceGroup, volumeID)
|
||||||
|
|
|
@ -137,16 +137,6 @@ func (b *blockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, e
|
||||||
return res.Type, nil, nil
|
return res.Type, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *blockStore) IsVolumeReady(volumeID, volumeAZ string) (ready bool, err error) {
|
|
||||||
disk, err := b.gce.Disks.Get(b.project, volumeAZ, volumeID).Do()
|
|
||||||
if err != nil {
|
|
||||||
return false, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO can we consider a disk ready while it's in the RESTORING state?
|
|
||||||
return disk.Status == "READY", 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
|
// snapshot names must adhere to RFC1035 and be 1-63 characters
|
||||||
// long
|
// long
|
||||||
|
|
|
@ -146,27 +146,6 @@ func (_m *BlockStore) Init(config map[string]string) error {
|
||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsVolumeReady provides a mock function with given fields: volumeID, volumeAZ
|
|
||||||
func (_m *BlockStore) IsVolumeReady(volumeID string, volumeAZ string) (bool, error) {
|
|
||||||
ret := _m.Called(volumeID, volumeAZ)
|
|
||||||
|
|
||||||
var r0 bool
|
|
||||||
if rf, ok := ret.Get(0).(func(string, string) bool); ok {
|
|
||||||
r0 = rf(volumeID, volumeAZ)
|
|
||||||
} else {
|
|
||||||
r0 = ret.Get(0).(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 error
|
|
||||||
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
|
||||||
r1 = rf(volumeID, volumeAZ)
|
|
||||||
} else {
|
|
||||||
r1 = ret.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetVolumeID provides a mock function with given fields: pv, volumeID
|
// SetVolumeID provides a mock function with given fields: pv, volumeID
|
||||||
func (_m *BlockStore) SetVolumeID(pv runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
func (_m *BlockStore) SetVolumeID(pv runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
||||||
ret := _m.Called(pv, volumeID)
|
ret := _m.Called(pv, volumeID)
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
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 cloudprovider
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SnapshotService exposes Ark-specific operations for snapshotting and restoring block
|
|
||||||
// volumes.
|
|
||||||
type SnapshotService interface {
|
|
||||||
// CreateSnapshot triggers a snapshot for the specified cloud volume and tags it with metadata.
|
|
||||||
// it returns the cloud snapshot ID, or an error if a problem is encountered triggering the snapshot via
|
|
||||||
// the cloud API.
|
|
||||||
CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error)
|
|
||||||
|
|
||||||
// CreateVolumeFromSnapshot triggers a restore operation to create a new cloud volume from the specified
|
|
||||||
// snapshot and volume characteristics. Returns the cloud volume ID, or an error if a problem is
|
|
||||||
// encountered triggering the restore via the cloud API.
|
|
||||||
CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (string, error)
|
|
||||||
|
|
||||||
// DeleteSnapshot triggers a deletion of the specified Ark snapshot via the cloud API. It returns an
|
|
||||||
// error if a problem is encountered triggering the deletion via the cloud API.
|
|
||||||
DeleteSnapshot(snapshotID string) error
|
|
||||||
|
|
||||||
// GetVolumeInfo gets the type and IOPS (if applicable) from the cloud API.
|
|
||||||
GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error)
|
|
||||||
|
|
||||||
// GetVolumeID returns the cloud provider specific identifier for the PersistentVolume.
|
|
||||||
GetVolumeID(pv runtime.Unstructured) (string, error)
|
|
||||||
|
|
||||||
// SetVolumeID sets the cloud provider specific identifier for the PersistentVolume.
|
|
||||||
SetVolumeID(pv runtime.Unstructured, volumeID string) (runtime.Unstructured, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
volumeCreateWaitTimeout = 30 * time.Second
|
|
||||||
volumeCreatePollInterval = 1 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
type snapshotService struct {
|
|
||||||
blockStore BlockStore
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ SnapshotService = &snapshotService{}
|
|
||||||
|
|
||||||
// NewSnapshotService creates a snapshot service using the provided block store
|
|
||||||
func NewSnapshotService(blockStore BlockStore) SnapshotService {
|
|
||||||
return &snapshotService{
|
|
||||||
blockStore: blockStore,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sr *snapshotService) CreateVolumeFromSnapshot(snapshotID string, volumeType string, volumeAZ string, iops *int64) (string, error) {
|
|
||||||
volumeID, err := sr.blockStore.CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ, iops)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for volume to be ready (up to a maximum time limit)
|
|
||||||
ticker := time.NewTicker(volumeCreatePollInterval)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
timeout := time.NewTimer(volumeCreateWaitTimeout)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-timeout.C:
|
|
||||||
return "", errors.Errorf("timeout reached waiting for volume %v to be ready", volumeID)
|
|
||||||
case <-ticker.C:
|
|
||||||
if ready, err := sr.blockStore.IsVolumeReady(volumeID, volumeAZ); err == nil && ready {
|
|
||||||
return volumeID, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sr *snapshotService) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
|
||||||
return sr.blockStore.CreateSnapshot(volumeID, volumeAZ, tags)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sr *snapshotService) DeleteSnapshot(snapshotID string) error {
|
|
||||||
return sr.blockStore.DeleteSnapshot(snapshotID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sr *snapshotService) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
|
||||||
return sr.blockStore.GetVolumeInfo(volumeID, volumeAZ)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sr *snapshotService) GetVolumeID(pv runtime.Unstructured) (string, error) {
|
|
||||||
return sr.blockStore.GetVolumeID(pv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sr *snapshotService) SetVolumeID(pv runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
|
||||||
return sr.blockStore.SetVolumeID(pv, volumeID)
|
|
||||||
}
|
|
|
@ -80,9 +80,6 @@ type BlockStore interface {
|
||||||
// the specified block volume in the given availability zone.
|
// the specified block volume in the given availability zone.
|
||||||
GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error)
|
GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error)
|
||||||
|
|
||||||
// IsVolumeReady returns whether the specified volume is ready to be used.
|
|
||||||
IsVolumeReady(volumeID, volumeAZ string) (ready bool, err error)
|
|
||||||
|
|
||||||
// CreateSnapshot creates a snapshot of the specified block volume, and applies the provided
|
// CreateSnapshot creates a snapshot of the specified block volume, and applies the provided
|
||||||
// set of tags to the snapshot.
|
// set of tags to the snapshot.
|
||||||
CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (snapshotID string, err error)
|
CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (snapshotID string, err error)
|
||||||
|
|
|
@ -149,7 +149,7 @@ type server struct {
|
||||||
kubeClient kubernetes.Interface
|
kubeClient kubernetes.Interface
|
||||||
arkClient clientset.Interface
|
arkClient clientset.Interface
|
||||||
objectStore cloudprovider.ObjectStore
|
objectStore cloudprovider.ObjectStore
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
discoveryClient discovery.DiscoveryInterface
|
discoveryClient discovery.DiscoveryInterface
|
||||||
discoveryHelper arkdiscovery.Helper
|
discoveryHelper arkdiscovery.Helper
|
||||||
dynamicClient dynamic.Interface
|
dynamicClient dynamic.Interface
|
||||||
|
@ -255,9 +255,16 @@ func (s *server) run() error {
|
||||||
}
|
}
|
||||||
s.objectStore = objectStore
|
s.objectStore = objectStore
|
||||||
|
|
||||||
if err := s.initSnapshotService(config); err != nil {
|
if config.PersistentVolumeProvider == nil {
|
||||||
|
s.logger.Info("PersistentVolumeProvider config not provided, volume snapshots and restores are disabled")
|
||||||
|
} else {
|
||||||
|
s.logger.Info("Configuring cloud provider for snapshot service")
|
||||||
|
blockStore, err := getBlockStore(*config.PersistentVolumeProvider, s.pluginManager)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
s.blockStore = blockStore
|
||||||
|
}
|
||||||
|
|
||||||
if config.BackupStorageProvider.ResticLocation != "" {
|
if config.BackupStorageProvider.ResticLocation != "" {
|
||||||
if err := s.initRestic(config.BackupStorageProvider); err != nil {
|
if err := s.initRestic(config.BackupStorageProvider); err != nil {
|
||||||
|
@ -464,21 +471,6 @@ func (s *server) watchConfig(config *api.Config) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) initSnapshotService(config *api.Config) error {
|
|
||||||
if config.PersistentVolumeProvider == nil {
|
|
||||||
s.logger.Info("PersistentVolumeProvider config not provided, volume snapshots and restores are disabled")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.Info("Configuring cloud provider for snapshot service")
|
|
||||||
blockStore, err := getBlockStore(*config.PersistentVolumeProvider, s.pluginManager)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s.snapshotService = cloudprovider.NewSnapshotService(blockStore)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getObjectStore(cloudConfig api.CloudProviderConfig, manager plugin.Manager) (cloudprovider.ObjectStore, error) {
|
func getObjectStore(cloudConfig api.CloudProviderConfig, manager plugin.Manager) (cloudprovider.ObjectStore, error) {
|
||||||
if cloudConfig.Name == "" {
|
if cloudConfig.Name == "" {
|
||||||
return nil, errors.New("object storage provider name must not be empty")
|
return nil, errors.New("object storage provider name must not be empty")
|
||||||
|
@ -620,7 +612,7 @@ func (s *server) runControllers(config *api.Config) error {
|
||||||
s.discoveryHelper,
|
s.discoveryHelper,
|
||||||
client.NewDynamicFactory(s.dynamicClient),
|
client.NewDynamicFactory(s.dynamicClient),
|
||||||
podexec.NewPodCommandExecutor(s.kubeClientConfig, s.kubeClient.CoreV1().RESTClient()),
|
podexec.NewPodCommandExecutor(s.kubeClientConfig, s.kubeClient.CoreV1().RESTClient()),
|
||||||
s.snapshotService,
|
s.blockStore,
|
||||||
s.resticManager,
|
s.resticManager,
|
||||||
config.PodVolumeOperationTimeout.Duration,
|
config.PodVolumeOperationTimeout.Duration,
|
||||||
)
|
)
|
||||||
|
@ -632,7 +624,7 @@ func (s *server) runControllers(config *api.Config) error {
|
||||||
backupper,
|
backupper,
|
||||||
config.BackupStorageProvider.CloudProviderConfig,
|
config.BackupStorageProvider.CloudProviderConfig,
|
||||||
config.BackupStorageProvider.Bucket,
|
config.BackupStorageProvider.Bucket,
|
||||||
s.snapshotService != nil,
|
s.blockStore != nil,
|
||||||
s.logger,
|
s.logger,
|
||||||
s.logLevel,
|
s.logLevel,
|
||||||
s.pluginRegistry,
|
s.pluginRegistry,
|
||||||
|
@ -678,7 +670,7 @@ func (s *server) runControllers(config *api.Config) error {
|
||||||
s.sharedInformerFactory.Ark().V1().DeleteBackupRequests(),
|
s.sharedInformerFactory.Ark().V1().DeleteBackupRequests(),
|
||||||
s.arkClient.ArkV1(), // deleteBackupRequestClient
|
s.arkClient.ArkV1(), // deleteBackupRequestClient
|
||||||
s.arkClient.ArkV1(), // backupClient
|
s.arkClient.ArkV1(), // backupClient
|
||||||
s.snapshotService,
|
s.blockStore,
|
||||||
s.objectStore,
|
s.objectStore,
|
||||||
config.BackupStorageProvider.Bucket,
|
config.BackupStorageProvider.Bucket,
|
||||||
s.sharedInformerFactory.Ark().V1().Restores(),
|
s.sharedInformerFactory.Ark().V1().Restores(),
|
||||||
|
@ -698,7 +690,7 @@ func (s *server) runControllers(config *api.Config) error {
|
||||||
restorer, err := restore.NewKubernetesRestorer(
|
restorer, err := restore.NewKubernetesRestorer(
|
||||||
s.discoveryHelper,
|
s.discoveryHelper,
|
||||||
client.NewDynamicFactory(s.dynamicClient),
|
client.NewDynamicFactory(s.dynamicClient),
|
||||||
s.snapshotService,
|
s.blockStore,
|
||||||
config.ResourcePriorities,
|
config.ResourcePriorities,
|
||||||
s.arkClient.ArkV1(),
|
s.arkClient.ArkV1(),
|
||||||
s.kubeClient.CoreV1().Namespaces(),
|
s.kubeClient.CoreV1().Namespaces(),
|
||||||
|
@ -717,7 +709,7 @@ func (s *server) runControllers(config *api.Config) error {
|
||||||
config.BackupStorageProvider.CloudProviderConfig,
|
config.BackupStorageProvider.CloudProviderConfig,
|
||||||
config.BackupStorageProvider.Bucket,
|
config.BackupStorageProvider.Bucket,
|
||||||
s.sharedInformerFactory.Ark().V1().Backups(),
|
s.sharedInformerFactory.Ark().V1().Backups(),
|
||||||
s.snapshotService != nil,
|
s.blockStore != nil,
|
||||||
s.logger,
|
s.logger,
|
||||||
s.logLevel,
|
s.logLevel,
|
||||||
s.pluginRegistry,
|
s.pluginRegistry,
|
||||||
|
|
|
@ -49,7 +49,7 @@ type backupDeletionController struct {
|
||||||
deleteBackupRequestClient arkv1client.DeleteBackupRequestsGetter
|
deleteBackupRequestClient arkv1client.DeleteBackupRequestsGetter
|
||||||
deleteBackupRequestLister listers.DeleteBackupRequestLister
|
deleteBackupRequestLister listers.DeleteBackupRequestLister
|
||||||
backupClient arkv1client.BackupsGetter
|
backupClient arkv1client.BackupsGetter
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
objectStore cloudprovider.ObjectStore
|
objectStore cloudprovider.ObjectStore
|
||||||
bucket string
|
bucket string
|
||||||
restoreLister listers.RestoreLister
|
restoreLister listers.RestoreLister
|
||||||
|
@ -69,7 +69,7 @@ func NewBackupDeletionController(
|
||||||
deleteBackupRequestInformer informers.DeleteBackupRequestInformer,
|
deleteBackupRequestInformer informers.DeleteBackupRequestInformer,
|
||||||
deleteBackupRequestClient arkv1client.DeleteBackupRequestsGetter,
|
deleteBackupRequestClient arkv1client.DeleteBackupRequestsGetter,
|
||||||
backupClient arkv1client.BackupsGetter,
|
backupClient arkv1client.BackupsGetter,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
objectStore cloudprovider.ObjectStore,
|
objectStore cloudprovider.ObjectStore,
|
||||||
bucket string,
|
bucket string,
|
||||||
restoreInformer informers.RestoreInformer,
|
restoreInformer informers.RestoreInformer,
|
||||||
|
@ -83,7 +83,7 @@ func NewBackupDeletionController(
|
||||||
deleteBackupRequestClient: deleteBackupRequestClient,
|
deleteBackupRequestClient: deleteBackupRequestClient,
|
||||||
deleteBackupRequestLister: deleteBackupRequestInformer.Lister(),
|
deleteBackupRequestLister: deleteBackupRequestInformer.Lister(),
|
||||||
backupClient: backupClient,
|
backupClient: backupClient,
|
||||||
snapshotService: snapshotService,
|
blockStore: blockStore,
|
||||||
objectStore: objectStore,
|
objectStore: objectStore,
|
||||||
bucket: bucket,
|
bucket: bucket,
|
||||||
restoreLister: restoreInformer.Lister(),
|
restoreLister: restoreInformer.Lister(),
|
||||||
|
@ -220,7 +220,7 @@ func (c *backupDeletionController) processRequest(req *v1.DeleteBackupRequest) e
|
||||||
|
|
||||||
// If the backup includes snapshots but we don't currently have a PVProvider, we don't
|
// If the backup includes snapshots but we don't currently have a PVProvider, we don't
|
||||||
// want to orphan the snapshots so skip deletion.
|
// want to orphan the snapshots so skip deletion.
|
||||||
if c.snapshotService == nil && len(backup.Status.VolumeBackups) > 0 {
|
if c.blockStore == nil && len(backup.Status.VolumeBackups) > 0 {
|
||||||
req, err = c.patchDeleteBackupRequest(req, func(r *v1.DeleteBackupRequest) {
|
req, err = c.patchDeleteBackupRequest(req, func(r *v1.DeleteBackupRequest) {
|
||||||
r.Status.Phase = v1.DeleteBackupRequestPhaseProcessed
|
r.Status.Phase = v1.DeleteBackupRequestPhaseProcessed
|
||||||
r.Status.Errors = []string{"unable to delete backup because it includes PV snapshots and Ark is not configured with a PersistentVolumeProvider"}
|
r.Status.Errors = []string{"unable to delete backup because it includes PV snapshots and Ark is not configured with a PersistentVolumeProvider"}
|
||||||
|
@ -244,7 +244,7 @@ func (c *backupDeletionController) processRequest(req *v1.DeleteBackupRequest) e
|
||||||
log.Info("Removing PV snapshots")
|
log.Info("Removing PV snapshots")
|
||||||
for _, volumeBackup := range backup.Status.VolumeBackups {
|
for _, volumeBackup := range backup.Status.VolumeBackups {
|
||||||
log.WithField("snapshotID", volumeBackup.SnapshotID).Info("Removing snapshot associated with backup")
|
log.WithField("snapshotID", volumeBackup.SnapshotID).Info("Removing snapshot associated with backup")
|
||||||
if err := c.snapshotService.DeleteSnapshot(volumeBackup.SnapshotID); err != nil {
|
if err := c.blockStore.DeleteSnapshot(volumeBackup.SnapshotID); err != nil {
|
||||||
errs = append(errs, errors.Wrapf(err, "error deleting snapshot %s", volumeBackup.SnapshotID).Error())
|
errs = append(errs, errors.Wrapf(err, "error deleting snapshot %s", volumeBackup.SnapshotID).Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ func TestBackupDeletionControllerProcessQueueItem(t *testing.T) {
|
||||||
sharedInformers.Ark().V1().DeleteBackupRequests(),
|
sharedInformers.Ark().V1().DeleteBackupRequests(),
|
||||||
client.ArkV1(), // deleteBackupRequestClient
|
client.ArkV1(), // deleteBackupRequestClient
|
||||||
client.ArkV1(), // backupClient
|
client.ArkV1(), // backupClient
|
||||||
nil, // snapshotService
|
nil, // blockStore
|
||||||
nil, // backupService
|
nil, // backupService
|
||||||
"bucket",
|
"bucket",
|
||||||
sharedInformers.Ark().V1().Restores(),
|
sharedInformers.Ark().V1().Restores(),
|
||||||
|
@ -108,7 +108,7 @@ func TestBackupDeletionControllerProcessQueueItem(t *testing.T) {
|
||||||
type backupDeletionControllerTestData struct {
|
type backupDeletionControllerTestData struct {
|
||||||
client *fake.Clientset
|
client *fake.Clientset
|
||||||
sharedInformers informers.SharedInformerFactory
|
sharedInformers informers.SharedInformerFactory
|
||||||
snapshotService *arktest.FakeSnapshotService
|
blockStore *arktest.FakeBlockStore
|
||||||
controller *backupDeletionController
|
controller *backupDeletionController
|
||||||
req *v1.DeleteBackupRequest
|
req *v1.DeleteBackupRequest
|
||||||
}
|
}
|
||||||
|
@ -116,19 +116,19 @@ type backupDeletionControllerTestData struct {
|
||||||
func setupBackupDeletionControllerTest(objects ...runtime.Object) *backupDeletionControllerTestData {
|
func setupBackupDeletionControllerTest(objects ...runtime.Object) *backupDeletionControllerTestData {
|
||||||
client := fake.NewSimpleClientset(objects...)
|
client := fake.NewSimpleClientset(objects...)
|
||||||
sharedInformers := informers.NewSharedInformerFactory(client, 0)
|
sharedInformers := informers.NewSharedInformerFactory(client, 0)
|
||||||
snapshotService := &arktest.FakeSnapshotService{SnapshotsTaken: sets.NewString()}
|
blockStore := &arktest.FakeBlockStore{SnapshotsTaken: sets.NewString()}
|
||||||
req := pkgbackup.NewDeleteBackupRequest("foo", "uid")
|
req := pkgbackup.NewDeleteBackupRequest("foo", "uid")
|
||||||
|
|
||||||
data := &backupDeletionControllerTestData{
|
data := &backupDeletionControllerTestData{
|
||||||
client: client,
|
client: client,
|
||||||
sharedInformers: sharedInformers,
|
sharedInformers: sharedInformers,
|
||||||
snapshotService: snapshotService,
|
blockStore: blockStore,
|
||||||
controller: NewBackupDeletionController(
|
controller: NewBackupDeletionController(
|
||||||
arktest.NewLogger(),
|
arktest.NewLogger(),
|
||||||
sharedInformers.Ark().V1().DeleteBackupRequests(),
|
sharedInformers.Ark().V1().DeleteBackupRequests(),
|
||||||
client.ArkV1(), // deleteBackupRequestClient
|
client.ArkV1(), // deleteBackupRequestClient
|
||||||
client.ArkV1(), // backupClient
|
client.ArkV1(), // backupClient
|
||||||
snapshotService,
|
blockStore,
|
||||||
nil, // objectStore
|
nil, // objectStore
|
||||||
"bucket",
|
"bucket",
|
||||||
sharedInformers.Ark().V1().Restores(),
|
sharedInformers.Ark().V1().Restores(),
|
||||||
|
@ -305,9 +305,9 @@ func TestBackupDeletionControllerProcessRequest(t *testing.T) {
|
||||||
assert.Equal(t, expectedActions, td.client.Actions())
|
assert.Equal(t, expectedActions, td.client.Actions())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("no snapshot service, backup has snapshots", func(t *testing.T) {
|
t.Run("no block store, backup has snapshots", func(t *testing.T) {
|
||||||
td := setupBackupDeletionControllerTest()
|
td := setupBackupDeletionControllerTest()
|
||||||
td.controller.snapshotService = nil
|
td.controller.blockStore = nil
|
||||||
|
|
||||||
td.client.PrependReactor("get", "backups", func(action core.Action) (bool, runtime.Object, error) {
|
td.client.PrependReactor("get", "backups", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
backup := arktest.NewTestBackup().WithName("backup-1").WithSnapshot("pv-1", "snap-1").Backup
|
backup := arktest.NewTestBackup().WithName("backup-1").WithSnapshot("pv-1", "snap-1").Backup
|
||||||
|
@ -364,7 +364,7 @@ func TestBackupDeletionControllerProcessRequest(t *testing.T) {
|
||||||
td.client.PrependReactor("get", "backups", func(action core.Action) (bool, runtime.Object, error) {
|
td.client.PrependReactor("get", "backups", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
return true, backup, nil
|
return true, backup, nil
|
||||||
})
|
})
|
||||||
td.snapshotService.SnapshotsTaken.Insert("snap-1")
|
td.blockStore.SnapshotsTaken.Insert("snap-1")
|
||||||
|
|
||||||
td.client.PrependReactor("patch", "deletebackuprequests", func(action core.Action) (bool, runtime.Object, error) {
|
td.client.PrependReactor("patch", "deletebackuprequests", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
return true, td.req, nil
|
return true, td.req, nil
|
||||||
|
@ -438,7 +438,7 @@ func TestBackupDeletionControllerProcessRequest(t *testing.T) {
|
||||||
arktest.CompareActions(t, expectedActions, td.client.Actions())
|
arktest.CompareActions(t, expectedActions, td.client.Actions())
|
||||||
|
|
||||||
// Make sure snapshot was deleted
|
// Make sure snapshot was deleted
|
||||||
assert.Equal(t, 0, td.snapshotService.SnapshotsTaken.Len())
|
assert.Equal(t, 0, td.blockStore.SnapshotsTaken.Len())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,7 +560,7 @@ func TestBackupDeletionControllerDeleteExpiredRequests(t *testing.T) {
|
||||||
sharedInformers.Ark().V1().DeleteBackupRequests(),
|
sharedInformers.Ark().V1().DeleteBackupRequests(),
|
||||||
client.ArkV1(), // deleteBackupRequestClient
|
client.ArkV1(), // deleteBackupRequestClient
|
||||||
client.ArkV1(), // backupClient
|
client.ArkV1(), // backupClient
|
||||||
nil, // snapshotService
|
nil, // blockStore
|
||||||
nil, // backupService
|
nil, // backupService
|
||||||
"bucket",
|
"bucket",
|
||||||
sharedInformers.Ark().V1().Restores(),
|
sharedInformers.Ark().V1().Restores(),
|
||||||
|
|
|
@ -117,16 +117,6 @@ func (c *BlockStoreGRPCClient) GetVolumeInfo(volumeID, volumeAZ string) (string,
|
||||||
return res.VolumeType, iops, nil
|
return res.VolumeType, iops, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsVolumeReady returns whether the specified volume is ready to be used.
|
|
||||||
func (c *BlockStoreGRPCClient) IsVolumeReady(volumeID, volumeAZ string) (bool, error) {
|
|
||||||
res, err := c.grpcClient.IsVolumeReady(context.Background(), &proto.IsVolumeReadyRequest{Plugin: c.plugin, VolumeID: volumeID, VolumeAZ: volumeAZ})
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.Ready, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateSnapshot creates a snapshot of the specified block volume, and applies the provided
|
// CreateSnapshot creates a snapshot of the specified block volume, and applies the provided
|
||||||
// set of tags to the snapshot.
|
// set of tags to the snapshot.
|
||||||
func (c *BlockStoreGRPCClient) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
func (c *BlockStoreGRPCClient) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||||
|
@ -292,21 +282,6 @@ func (s *BlockStoreGRPCServer) GetVolumeInfo(ctx context.Context, req *proto.Get
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsVolumeReady returns whether the specified volume is ready to be used.
|
|
||||||
func (s *BlockStoreGRPCServer) IsVolumeReady(ctx context.Context, req *proto.IsVolumeReadyRequest) (*proto.IsVolumeReadyResponse, error) {
|
|
||||||
impl, err := s.getImpl(req.Plugin)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ready, err := impl.IsVolumeReady(req.VolumeID, req.VolumeAZ)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &proto.IsVolumeReadyResponse{Ready: ready}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateSnapshot creates a snapshot of the specified block volume, and applies the provided
|
// CreateSnapshot creates a snapshot of the specified block volume, and applies the provided
|
||||||
// set of tags to the snapshot.
|
// set of tags to the snapshot.
|
||||||
func (s *BlockStoreGRPCServer) CreateSnapshot(ctx context.Context, req *proto.CreateSnapshotRequest) (*proto.CreateSnapshotResponse, error) {
|
func (s *BlockStoreGRPCServer) CreateSnapshot(ctx context.Context, req *proto.CreateSnapshotRequest) (*proto.CreateSnapshotResponse, error) {
|
||||||
|
|
|
@ -20,8 +20,6 @@ It has these top-level messages:
|
||||||
CreateVolumeResponse
|
CreateVolumeResponse
|
||||||
GetVolumeInfoRequest
|
GetVolumeInfoRequest
|
||||||
GetVolumeInfoResponse
|
GetVolumeInfoResponse
|
||||||
IsVolumeReadyRequest
|
|
||||||
IsVolumeReadyResponse
|
|
||||||
CreateSnapshotRequest
|
CreateSnapshotRequest
|
||||||
CreateSnapshotResponse
|
CreateSnapshotResponse
|
||||||
DeleteSnapshotRequest
|
DeleteSnapshotRequest
|
||||||
|
|
|
@ -137,54 +137,6 @@ func (m *GetVolumeInfoResponse) GetIops() int64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type IsVolumeReadyRequest struct {
|
|
||||||
Plugin string `protobuf:"bytes,1,opt,name=plugin" json:"plugin,omitempty"`
|
|
||||||
VolumeID string `protobuf:"bytes,2,opt,name=volumeID" json:"volumeID,omitempty"`
|
|
||||||
VolumeAZ string `protobuf:"bytes,3,opt,name=volumeAZ" json:"volumeAZ,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *IsVolumeReadyRequest) Reset() { *m = IsVolumeReadyRequest{} }
|
|
||||||
func (m *IsVolumeReadyRequest) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*IsVolumeReadyRequest) ProtoMessage() {}
|
|
||||||
func (*IsVolumeReadyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} }
|
|
||||||
|
|
||||||
func (m *IsVolumeReadyRequest) GetPlugin() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.Plugin
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *IsVolumeReadyRequest) GetVolumeID() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.VolumeID
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *IsVolumeReadyRequest) GetVolumeAZ() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.VolumeAZ
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type IsVolumeReadyResponse struct {
|
|
||||||
Ready bool `protobuf:"varint,1,opt,name=ready" json:"ready,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *IsVolumeReadyResponse) Reset() { *m = IsVolumeReadyResponse{} }
|
|
||||||
func (m *IsVolumeReadyResponse) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*IsVolumeReadyResponse) ProtoMessage() {}
|
|
||||||
func (*IsVolumeReadyResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} }
|
|
||||||
|
|
||||||
func (m *IsVolumeReadyResponse) GetReady() bool {
|
|
||||||
if m != nil {
|
|
||||||
return m.Ready
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateSnapshotRequest struct {
|
type CreateSnapshotRequest struct {
|
||||||
Plugin string `protobuf:"bytes,1,opt,name=plugin" json:"plugin,omitempty"`
|
Plugin string `protobuf:"bytes,1,opt,name=plugin" json:"plugin,omitempty"`
|
||||||
VolumeID string `protobuf:"bytes,2,opt,name=volumeID" json:"volumeID,omitempty"`
|
VolumeID string `protobuf:"bytes,2,opt,name=volumeID" json:"volumeID,omitempty"`
|
||||||
|
@ -358,8 +310,6 @@ func init() {
|
||||||
proto.RegisterType((*CreateVolumeResponse)(nil), "generated.CreateVolumeResponse")
|
proto.RegisterType((*CreateVolumeResponse)(nil), "generated.CreateVolumeResponse")
|
||||||
proto.RegisterType((*GetVolumeInfoRequest)(nil), "generated.GetVolumeInfoRequest")
|
proto.RegisterType((*GetVolumeInfoRequest)(nil), "generated.GetVolumeInfoRequest")
|
||||||
proto.RegisterType((*GetVolumeInfoResponse)(nil), "generated.GetVolumeInfoResponse")
|
proto.RegisterType((*GetVolumeInfoResponse)(nil), "generated.GetVolumeInfoResponse")
|
||||||
proto.RegisterType((*IsVolumeReadyRequest)(nil), "generated.IsVolumeReadyRequest")
|
|
||||||
proto.RegisterType((*IsVolumeReadyResponse)(nil), "generated.IsVolumeReadyResponse")
|
|
||||||
proto.RegisterType((*CreateSnapshotRequest)(nil), "generated.CreateSnapshotRequest")
|
proto.RegisterType((*CreateSnapshotRequest)(nil), "generated.CreateSnapshotRequest")
|
||||||
proto.RegisterType((*CreateSnapshotResponse)(nil), "generated.CreateSnapshotResponse")
|
proto.RegisterType((*CreateSnapshotResponse)(nil), "generated.CreateSnapshotResponse")
|
||||||
proto.RegisterType((*DeleteSnapshotRequest)(nil), "generated.DeleteSnapshotRequest")
|
proto.RegisterType((*DeleteSnapshotRequest)(nil), "generated.DeleteSnapshotRequest")
|
||||||
|
@ -383,7 +333,6 @@ type BlockStoreClient interface {
|
||||||
Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*Empty, error)
|
Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*Empty, error)
|
||||||
CreateVolumeFromSnapshot(ctx context.Context, in *CreateVolumeRequest, opts ...grpc.CallOption) (*CreateVolumeResponse, error)
|
CreateVolumeFromSnapshot(ctx context.Context, in *CreateVolumeRequest, opts ...grpc.CallOption) (*CreateVolumeResponse, error)
|
||||||
GetVolumeInfo(ctx context.Context, in *GetVolumeInfoRequest, opts ...grpc.CallOption) (*GetVolumeInfoResponse, error)
|
GetVolumeInfo(ctx context.Context, in *GetVolumeInfoRequest, opts ...grpc.CallOption) (*GetVolumeInfoResponse, error)
|
||||||
IsVolumeReady(ctx context.Context, in *IsVolumeReadyRequest, opts ...grpc.CallOption) (*IsVolumeReadyResponse, error)
|
|
||||||
CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error)
|
CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error)
|
||||||
DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*Empty, error)
|
DeleteSnapshot(ctx context.Context, in *DeleteSnapshotRequest, opts ...grpc.CallOption) (*Empty, error)
|
||||||
GetVolumeID(ctx context.Context, in *GetVolumeIDRequest, opts ...grpc.CallOption) (*GetVolumeIDResponse, error)
|
GetVolumeID(ctx context.Context, in *GetVolumeIDRequest, opts ...grpc.CallOption) (*GetVolumeIDResponse, error)
|
||||||
|
@ -425,15 +374,6 @@ func (c *blockStoreClient) GetVolumeInfo(ctx context.Context, in *GetVolumeInfoR
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *blockStoreClient) IsVolumeReady(ctx context.Context, in *IsVolumeReadyRequest, opts ...grpc.CallOption) (*IsVolumeReadyResponse, error) {
|
|
||||||
out := new(IsVolumeReadyResponse)
|
|
||||||
err := grpc.Invoke(ctx, "/generated.BlockStore/IsVolumeReady", in, out, c.cc, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *blockStoreClient) CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) {
|
func (c *blockStoreClient) CreateSnapshot(ctx context.Context, in *CreateSnapshotRequest, opts ...grpc.CallOption) (*CreateSnapshotResponse, error) {
|
||||||
out := new(CreateSnapshotResponse)
|
out := new(CreateSnapshotResponse)
|
||||||
err := grpc.Invoke(ctx, "/generated.BlockStore/CreateSnapshot", in, out, c.cc, opts...)
|
err := grpc.Invoke(ctx, "/generated.BlockStore/CreateSnapshot", in, out, c.cc, opts...)
|
||||||
|
@ -476,7 +416,6 @@ type BlockStoreServer interface {
|
||||||
Init(context.Context, *InitRequest) (*Empty, error)
|
Init(context.Context, *InitRequest) (*Empty, error)
|
||||||
CreateVolumeFromSnapshot(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error)
|
CreateVolumeFromSnapshot(context.Context, *CreateVolumeRequest) (*CreateVolumeResponse, error)
|
||||||
GetVolumeInfo(context.Context, *GetVolumeInfoRequest) (*GetVolumeInfoResponse, error)
|
GetVolumeInfo(context.Context, *GetVolumeInfoRequest) (*GetVolumeInfoResponse, error)
|
||||||
IsVolumeReady(context.Context, *IsVolumeReadyRequest) (*IsVolumeReadyResponse, error)
|
|
||||||
CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error)
|
CreateSnapshot(context.Context, *CreateSnapshotRequest) (*CreateSnapshotResponse, error)
|
||||||
DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*Empty, error)
|
DeleteSnapshot(context.Context, *DeleteSnapshotRequest) (*Empty, error)
|
||||||
GetVolumeID(context.Context, *GetVolumeIDRequest) (*GetVolumeIDResponse, error)
|
GetVolumeID(context.Context, *GetVolumeIDRequest) (*GetVolumeIDResponse, error)
|
||||||
|
@ -541,24 +480,6 @@ func _BlockStore_GetVolumeInfo_Handler(srv interface{}, ctx context.Context, dec
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _BlockStore_IsVolumeReady_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(IsVolumeReadyRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(BlockStoreServer).IsVolumeReady(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/generated.BlockStore/IsVolumeReady",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(BlockStoreServer).IsVolumeReady(ctx, req.(*IsVolumeReadyRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _BlockStore_CreateSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _BlockStore_CreateSnapshot_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(CreateSnapshotRequest)
|
in := new(CreateSnapshotRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
|
@ -647,10 +568,6 @@ var _BlockStore_serviceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "GetVolumeInfo",
|
MethodName: "GetVolumeInfo",
|
||||||
Handler: _BlockStore_GetVolumeInfo_Handler,
|
Handler: _BlockStore_GetVolumeInfo_Handler,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MethodName: "IsVolumeReady",
|
|
||||||
Handler: _BlockStore_IsVolumeReady_Handler,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
MethodName: "CreateSnapshot",
|
MethodName: "CreateSnapshot",
|
||||||
Handler: _BlockStore_CreateSnapshot_Handler,
|
Handler: _BlockStore_CreateSnapshot_Handler,
|
||||||
|
|
|
@ -26,16 +26,6 @@ message GetVolumeInfoResponse {
|
||||||
int64 iops = 2;
|
int64 iops = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message IsVolumeReadyRequest {
|
|
||||||
string plugin = 1;
|
|
||||||
string volumeID = 2;
|
|
||||||
string volumeAZ = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message IsVolumeReadyResponse {
|
|
||||||
bool ready = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CreateSnapshotRequest {
|
message CreateSnapshotRequest {
|
||||||
string plugin = 1;
|
string plugin = 1;
|
||||||
string volumeID = 2;
|
string volumeID = 2;
|
||||||
|
@ -75,7 +65,6 @@ service BlockStore {
|
||||||
rpc Init(InitRequest) returns (Empty);
|
rpc Init(InitRequest) returns (Empty);
|
||||||
rpc CreateVolumeFromSnapshot(CreateVolumeRequest) returns (CreateVolumeResponse);
|
rpc CreateVolumeFromSnapshot(CreateVolumeRequest) returns (CreateVolumeResponse);
|
||||||
rpc GetVolumeInfo(GetVolumeInfoRequest) returns (GetVolumeInfoResponse);
|
rpc GetVolumeInfo(GetVolumeInfoRequest) returns (GetVolumeInfoResponse);
|
||||||
rpc IsVolumeReady(IsVolumeReadyRequest) returns (IsVolumeReadyResponse);
|
|
||||||
rpc CreateSnapshot(CreateSnapshotRequest) returns (CreateSnapshotResponse);
|
rpc CreateSnapshot(CreateSnapshotRequest) returns (CreateSnapshotResponse);
|
||||||
rpc DeleteSnapshot(DeleteSnapshotRequest) returns (Empty);
|
rpc DeleteSnapshot(DeleteSnapshotRequest) returns (Empty);
|
||||||
rpc GetVolumeID(GetVolumeIDRequest) returns (GetVolumeIDResponse);
|
rpc GetVolumeID(GetVolumeIDRequest) returns (GetVolumeIDResponse);
|
||||||
|
|
|
@ -139,15 +139,6 @@ func (r *restartableBlockStore) GetVolumeInfo(volumeID string, volumeAZ string)
|
||||||
return delegate.GetVolumeInfo(volumeID, volumeAZ)
|
return delegate.GetVolumeInfo(volumeID, volumeAZ)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsVolumeReady restarts the plugin's process if needed, then delegates the call.
|
|
||||||
func (r *restartableBlockStore) IsVolumeReady(volumeID string, volumeAZ string) (ready bool, err error) {
|
|
||||||
delegate, err := r.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return delegate.IsVolumeReady(volumeID, volumeAZ)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateSnapshot restarts the plugin's process if needed, then delegates the call.
|
// CreateSnapshot restarts the plugin's process if needed, then delegates the call.
|
||||||
func (r *restartableBlockStore) CreateSnapshot(volumeID string, volumeAZ string, tags map[string]string) (snapshotID string, err error) {
|
func (r *restartableBlockStore) CreateSnapshot(volumeID string, volumeAZ string, tags map[string]string) (snapshotID string, err error) {
|
||||||
delegate, err := r.getDelegate()
|
delegate, err := r.getDelegate()
|
||||||
|
|
|
@ -229,12 +229,6 @@ func TestRestartableBlockStoreDelegatedFunctions(t *testing.T) {
|
||||||
expectedErrorOutputs: []interface{}{"", (*int64)(nil), errors.Errorf("reset error")},
|
expectedErrorOutputs: []interface{}{"", (*int64)(nil), errors.Errorf("reset error")},
|
||||||
expectedDelegateOutputs: []interface{}{"volumeType", to.Int64Ptr(10000), errors.Errorf("delegate error")},
|
expectedDelegateOutputs: []interface{}{"volumeType", to.Int64Ptr(10000), errors.Errorf("delegate error")},
|
||||||
},
|
},
|
||||||
restartableDelegateTest{
|
|
||||||
function: "IsVolumeReady",
|
|
||||||
inputs: []interface{}{"volumeID", "volumeAZ"},
|
|
||||||
expectedErrorOutputs: []interface{}{false, errors.Errorf("reset error")},
|
|
||||||
expectedDelegateOutputs: []interface{}{true, errors.Errorf("delegate error")},
|
|
||||||
},
|
|
||||||
restartableDelegateTest{
|
restartableDelegateTest{
|
||||||
function: "CreateSnapshot",
|
function: "CreateSnapshot",
|
||||||
inputs: []interface{}{"volumeID", "volumeAZ", map[string]string{"a": "b"}},
|
inputs: []interface{}{"volumeID", "volumeAZ", map[string]string{"a": "b"}},
|
||||||
|
|
|
@ -73,7 +73,7 @@ type kindString string
|
||||||
type kubernetesRestorer struct {
|
type kubernetesRestorer struct {
|
||||||
discoveryHelper discovery.Helper
|
discoveryHelper discovery.Helper
|
||||||
dynamicFactory client.DynamicFactory
|
dynamicFactory client.DynamicFactory
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
backupClient arkv1client.BackupsGetter
|
backupClient arkv1client.BackupsGetter
|
||||||
namespaceClient corev1.NamespaceInterface
|
namespaceClient corev1.NamespaceInterface
|
||||||
resticRestorerFactory restic.RestorerFactory
|
resticRestorerFactory restic.RestorerFactory
|
||||||
|
@ -145,7 +145,7 @@ func prioritizeResources(helper discovery.Helper, priorities []string, includedR
|
||||||
func NewKubernetesRestorer(
|
func NewKubernetesRestorer(
|
||||||
discoveryHelper discovery.Helper,
|
discoveryHelper discovery.Helper,
|
||||||
dynamicFactory client.DynamicFactory,
|
dynamicFactory client.DynamicFactory,
|
||||||
snapshotService cloudprovider.SnapshotService,
|
blockStore cloudprovider.BlockStore,
|
||||||
resourcePriorities []string,
|
resourcePriorities []string,
|
||||||
backupClient arkv1client.BackupsGetter,
|
backupClient arkv1client.BackupsGetter,
|
||||||
namespaceClient corev1.NamespaceInterface,
|
namespaceClient corev1.NamespaceInterface,
|
||||||
|
@ -156,7 +156,7 @@ func NewKubernetesRestorer(
|
||||||
return &kubernetesRestorer{
|
return &kubernetesRestorer{
|
||||||
discoveryHelper: discoveryHelper,
|
discoveryHelper: discoveryHelper,
|
||||||
dynamicFactory: dynamicFactory,
|
dynamicFactory: dynamicFactory,
|
||||||
snapshotService: snapshotService,
|
blockStore: blockStore,
|
||||||
backupClient: backupClient,
|
backupClient: backupClient,
|
||||||
namespaceClient: namespaceClient,
|
namespaceClient: namespaceClient,
|
||||||
resticRestorerFactory: resticRestorerFactory,
|
resticRestorerFactory: resticRestorerFactory,
|
||||||
|
@ -224,7 +224,7 @@ func (kr *kubernetesRestorer) Restore(log logrus.FieldLogger, restore *api.Resto
|
||||||
snapshotVolumes: backup.Spec.SnapshotVolumes,
|
snapshotVolumes: backup.Spec.SnapshotVolumes,
|
||||||
restorePVs: restore.Spec.RestorePVs,
|
restorePVs: restore.Spec.RestorePVs,
|
||||||
volumeBackups: backup.Status.VolumeBackups,
|
volumeBackups: backup.Status.VolumeBackups,
|
||||||
snapshotService: kr.snapshotService,
|
blockStore: kr.blockStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreCtx := &context{
|
restoreCtx := &context{
|
||||||
|
@ -238,7 +238,7 @@ func (kr *kubernetesRestorer) Restore(log logrus.FieldLogger, restore *api.Resto
|
||||||
fileSystem: kr.fileSystem,
|
fileSystem: kr.fileSystem,
|
||||||
namespaceClient: kr.namespaceClient,
|
namespaceClient: kr.namespaceClient,
|
||||||
actions: resolvedActions,
|
actions: resolvedActions,
|
||||||
snapshotService: kr.snapshotService,
|
blockStore: kr.blockStore,
|
||||||
resticRestorer: resticRestorer,
|
resticRestorer: resticRestorer,
|
||||||
pvsToProvision: sets.NewString(),
|
pvsToProvision: sets.NewString(),
|
||||||
pvRestorer: pvRestorer,
|
pvRestorer: pvRestorer,
|
||||||
|
@ -319,7 +319,7 @@ type context struct {
|
||||||
fileSystem filesystem.Interface
|
fileSystem filesystem.Interface
|
||||||
namespaceClient corev1.NamespaceInterface
|
namespaceClient corev1.NamespaceInterface
|
||||||
actions []resolvedAction
|
actions []resolvedAction
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
resticRestorer restic.Restorer
|
resticRestorer restic.Restorer
|
||||||
globalWaitGroup arksync.ErrorGroup
|
globalWaitGroup arksync.ErrorGroup
|
||||||
resourceWaitGroup sync.WaitGroup
|
resourceWaitGroup sync.WaitGroup
|
||||||
|
@ -901,7 +901,7 @@ type pvRestorer struct {
|
||||||
snapshotVolumes *bool
|
snapshotVolumes *bool
|
||||||
restorePVs *bool
|
restorePVs *bool
|
||||||
volumeBackups map[string]*api.VolumeBackupInfo
|
volumeBackups map[string]*api.VolumeBackupInfo
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *pvRestorer) executePVAction(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
func (r *pvRestorer) executePVAction(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
||||||
|
@ -937,7 +937,7 @@ func (r *pvRestorer) executePVAction(obj *unstructured.Unstructured) (*unstructu
|
||||||
|
|
||||||
// Past this point, we expect to be doing a restore
|
// Past this point, we expect to be doing a restore
|
||||||
|
|
||||||
if r.snapshotService == nil {
|
if r.blockStore == nil {
|
||||||
return nil, errors.New("you must configure a persistentVolumeProvider to restore PersistentVolumes from snapshots")
|
return nil, errors.New("you must configure a persistentVolumeProvider to restore PersistentVolumes from snapshots")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,13 +949,13 @@ func (r *pvRestorer) executePVAction(obj *unstructured.Unstructured) (*unstructu
|
||||||
)
|
)
|
||||||
|
|
||||||
log.Info("restoring persistent volume from snapshot")
|
log.Info("restoring persistent volume from snapshot")
|
||||||
volumeID, err := r.snapshotService.CreateVolumeFromSnapshot(backupInfo.SnapshotID, backupInfo.Type, backupInfo.AvailabilityZone, backupInfo.Iops)
|
volumeID, err := r.blockStore.CreateVolumeFromSnapshot(backupInfo.SnapshotID, backupInfo.Type, backupInfo.AvailabilityZone, backupInfo.Iops)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.Info("successfully restored persistent volume from snapshot")
|
log.Info("successfully restored persistent volume from snapshot")
|
||||||
|
|
||||||
updated1, err := r.snapshotService.SetVolumeID(obj, volumeID)
|
updated1, err := r.blockStore.SetVolumeID(obj, volumeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1193,7 +1193,7 @@ func TestExecutePVAction(t *testing.T) {
|
||||||
restore *api.Restore
|
restore *api.Restore
|
||||||
backup *api.Backup
|
backup *api.Backup
|
||||||
volumeMap map[api.VolumeBackupInfo]string
|
volumeMap map[api.VolumeBackupInfo]string
|
||||||
noSnapshotService bool
|
noBlockStore bool
|
||||||
expectedErr bool
|
expectedErr bool
|
||||||
expectedRes *unstructured.Unstructured
|
expectedRes *unstructured.Unstructured
|
||||||
volumeID string
|
volumeID string
|
||||||
|
@ -1261,13 +1261,13 @@ func TestExecutePVAction(t *testing.T) {
|
||||||
expectedRes: NewTestUnstructured().WithName("pv-1").WithSpec("xyz").Unstructured,
|
expectedRes: NewTestUnstructured().WithName("pv-1").WithSpec("xyz").Unstructured,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "restoring, snapshotService=nil, backup has at least 1 snapshot -> error",
|
name: "restoring, blockStore=nil, backup has at least 1 snapshot -> error",
|
||||||
obj: NewTestUnstructured().WithName("pv-1").WithSpecField("awsElasticBlockStore", make(map[string]interface{})).Unstructured,
|
obj: NewTestUnstructured().WithName("pv-1").WithSpecField("awsElasticBlockStore", make(map[string]interface{})).Unstructured,
|
||||||
restore: arktest.NewDefaultTestRestore().Restore,
|
restore: arktest.NewDefaultTestRestore().Restore,
|
||||||
backup: &api.Backup{Status: api.BackupStatus{VolumeBackups: map[string]*api.VolumeBackupInfo{"pv-1": {SnapshotID: "snap-1"}}}},
|
backup: &api.Backup{Status: api.BackupStatus{VolumeBackups: map[string]*api.VolumeBackupInfo{"pv-1": {SnapshotID: "snap-1"}}}},
|
||||||
volumeMap: map[api.VolumeBackupInfo]string{{SnapshotID: "snap-1"}: "volume-1"},
|
volumeMap: map[api.VolumeBackupInfo]string{{SnapshotID: "snap-1"}: "volume-1"},
|
||||||
volumeID: "volume-1",
|
volumeID: "volume-1",
|
||||||
noSnapshotService: true,
|
noBlockStore: true,
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
expectedRes: NewTestUnstructured().WithName("pv-1").WithSpecField("awsElasticBlockStore", make(map[string]interface{})).Unstructured,
|
expectedRes: NewTestUnstructured().WithName("pv-1").WithSpecField("awsElasticBlockStore", make(map[string]interface{})).Unstructured,
|
||||||
},
|
},
|
||||||
|
@ -1276,21 +1276,21 @@ func TestExecutePVAction(t *testing.T) {
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
snapshotService cloudprovider.SnapshotService
|
blockStore cloudprovider.BlockStore
|
||||||
fakeSnapshotService *arktest.FakeSnapshotService
|
fakeBlockStore *arktest.FakeBlockStore
|
||||||
)
|
)
|
||||||
if !test.noSnapshotService {
|
if !test.noBlockStore {
|
||||||
fakeSnapshotService = &arktest.FakeSnapshotService{
|
fakeBlockStore = &arktest.FakeBlockStore{
|
||||||
RestorableVolumes: test.volumeMap,
|
RestorableVolumes: test.volumeMap,
|
||||||
VolumeID: test.volumeID,
|
VolumeID: test.volumeID,
|
||||||
}
|
}
|
||||||
snapshotService = fakeSnapshotService
|
blockStore = fakeBlockStore
|
||||||
}
|
}
|
||||||
|
|
||||||
r := &pvRestorer{
|
r := &pvRestorer{
|
||||||
logger: arktest.NewLogger(),
|
logger: arktest.NewLogger(),
|
||||||
restorePVs: test.restore.Spec.RestorePVs,
|
restorePVs: test.restore.Spec.RestorePVs,
|
||||||
snapshotService: snapshotService,
|
blockStore: blockStore,
|
||||||
}
|
}
|
||||||
if test.backup != nil {
|
if test.backup != nil {
|
||||||
r.snapshotVolumes = test.backup.Spec.SnapshotVolumes
|
r.snapshotVolumes = test.backup.Spec.SnapshotVolumes
|
||||||
|
@ -1306,9 +1306,9 @@ func TestExecutePVAction(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
if test.expectSetVolumeID {
|
if test.expectSetVolumeID {
|
||||||
assert.Equal(t, test.volumeID, fakeSnapshotService.VolumeIDSet)
|
assert.Equal(t, test.volumeID, fakeBlockStore.VolumeIDSet)
|
||||||
} else {
|
} else {
|
||||||
assert.Equal(t, "", fakeSnapshotService.VolumeIDSet)
|
assert.Equal(t, "", fakeBlockStore.VolumeIDSet)
|
||||||
}
|
}
|
||||||
assert.Equal(t, test.expectedRes, res)
|
assert.Equal(t, test.expectedRes, res)
|
||||||
})
|
})
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
api "github.com/heptio/ark/pkg/apis/ark/v1"
|
api "github.com/heptio/ark/pkg/apis/ark/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FakeSnapshotService struct {
|
type FakeBlockStore struct {
|
||||||
// SnapshotID->VolumeID
|
// SnapshotID->VolumeID
|
||||||
SnapshotsTaken sets.String
|
SnapshotsTaken sets.String
|
||||||
|
|
||||||
|
@ -41,26 +41,30 @@ type FakeSnapshotService struct {
|
||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FakeSnapshotService) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
func (bs *FakeBlockStore) Init(config map[string]string) error {
|
||||||
if s.Error != nil {
|
return nil
|
||||||
return "", s.Error
|
}
|
||||||
|
|
||||||
|
func (bs *FakeBlockStore) CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (string, error) {
|
||||||
|
if bs.Error != nil {
|
||||||
|
return "", bs.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := s.SnapshottableVolumes[volumeID]; !exists {
|
if _, exists := bs.SnapshottableVolumes[volumeID]; !exists {
|
||||||
return "", errors.New("snapshottable volume not found")
|
return "", errors.New("snapshottable volume not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.SnapshotsTaken == nil {
|
if bs.SnapshotsTaken == nil {
|
||||||
s.SnapshotsTaken = sets.NewString()
|
bs.SnapshotsTaken = sets.NewString()
|
||||||
}
|
}
|
||||||
s.SnapshotsTaken.Insert(s.SnapshottableVolumes[volumeID].SnapshotID)
|
bs.SnapshotsTaken.Insert(bs.SnapshottableVolumes[volumeID].SnapshotID)
|
||||||
|
|
||||||
return s.SnapshottableVolumes[volumeID].SnapshotID, nil
|
return bs.SnapshottableVolumes[volumeID].SnapshotID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FakeSnapshotService) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (string, error) {
|
func (bs *FakeBlockStore) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (string, error) {
|
||||||
if s.Error != nil {
|
if bs.Error != nil {
|
||||||
return "", s.Error
|
return "", bs.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
key := api.VolumeBackupInfo{
|
key := api.VolumeBackupInfo{
|
||||||
|
@ -70,44 +74,44 @@ func (s *FakeSnapshotService) CreateVolumeFromSnapshot(snapshotID, volumeType, v
|
||||||
AvailabilityZone: volumeAZ,
|
AvailabilityZone: volumeAZ,
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.RestorableVolumes[key], nil
|
return bs.RestorableVolumes[key], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FakeSnapshotService) DeleteSnapshot(snapshotID string) error {
|
func (bs *FakeBlockStore) DeleteSnapshot(snapshotID string) error {
|
||||||
if s.Error != nil {
|
if bs.Error != nil {
|
||||||
return s.Error
|
return bs.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.SnapshotsTaken.Has(snapshotID) {
|
if !bs.SnapshotsTaken.Has(snapshotID) {
|
||||||
return errors.New("snapshot not found")
|
return errors.New("snapshot not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
s.SnapshotsTaken.Delete(snapshotID)
|
bs.SnapshotsTaken.Delete(snapshotID)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FakeSnapshotService) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
func (bs *FakeBlockStore) GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error) {
|
||||||
if s.Error != nil {
|
if bs.Error != nil {
|
||||||
return "", nil, s.Error
|
return "", nil, bs.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
if volumeInfo, exists := s.SnapshottableVolumes[volumeID]; !exists {
|
if volumeInfo, exists := bs.SnapshottableVolumes[volumeID]; !exists {
|
||||||
return "", nil, errors.New("VolumeID not found")
|
return "", nil, errors.New("VolumeID not found")
|
||||||
} else {
|
} else {
|
||||||
return volumeInfo.Type, volumeInfo.Iops, nil
|
return volumeInfo.Type, volumeInfo.Iops, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FakeSnapshotService) GetVolumeID(pv runtime.Unstructured) (string, error) {
|
func (bs *FakeBlockStore) GetVolumeID(pv runtime.Unstructured) (string, error) {
|
||||||
if s.Error != nil {
|
if bs.Error != nil {
|
||||||
return "", s.Error
|
return "", bs.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.VolumeID, nil
|
return bs.VolumeID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FakeSnapshotService) SetVolumeID(pv runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
func (bs *FakeBlockStore) SetVolumeID(pv runtime.Unstructured, volumeID string) (runtime.Unstructured, error) {
|
||||||
s.VolumeIDSet = volumeID
|
bs.VolumeIDSet = volumeID
|
||||||
return pv, s.Error
|
return pv, bs.Error
|
||||||
}
|
}
|
Loading…
Reference in New Issue