From 84df82c26fe20744739c5da6af00dcf11a9d986f Mon Sep 17 00:00:00 2001 From: Julian Sommer <115516918+juliansommer@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:21:02 +1100 Subject: [PATCH] fix: accept the snapshot-id filter on DescribeVolumes and match it against the volume's source snapshot (#1229) --- spinifex/domains/ec2/volume/service_impl.go | 5 +++ .../domains/ec2/volume/service_impl_test.go | 34 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/spinifex/domains/ec2/volume/service_impl.go b/spinifex/domains/ec2/volume/service_impl.go index e40ca82b9..85e7ceed5 100644 --- a/spinifex/domains/ec2/volume/service_impl.go +++ b/spinifex/domains/ec2/volume/service_impl.go @@ -289,6 +289,7 @@ var describeVolumesValidFilters = map[string]bool{ "attachment.status": true, "attachment.device": true, "availability-zone": true, + "snapshot-id": true, } // DescribeVolumes lists EBS volumes by reading config.json files from S3. @@ -401,6 +402,10 @@ func volumeMatchesFilters(vol *ec2.Volume, filters map[string][]string) bool { if vol.AvailabilityZone != nil { field = *vol.AvailabilityZone } + case "snapshot-id": + if vol.SnapshotId != nil { + field = *vol.SnapshotId + } default: return false } diff --git a/spinifex/domains/ec2/volume/service_impl_test.go b/spinifex/domains/ec2/volume/service_impl_test.go index bb9ee932a..9218cfedd 100644 --- a/spinifex/domains/ec2/volume/service_impl_test.go +++ b/spinifex/domains/ec2/volume/service_impl_test.go @@ -2081,6 +2081,40 @@ func TestDescribeVolumes_FilterByAZ(t *testing.T) { assert.Equal(t, "vol-az1", *out.Volumes[0].VolumeId) } +func TestDescribeVolumes_FilterBySnapshotId(t *testing.T) { + store := objectstore.NewMemoryObjectStore() + svc := newTestVolumeServiceWithStore("ap-southeast-2a", store) + + createVolumeInStoreWithMeta(t, svc, store, "vol-fromsnap", ebsmetadata.Volume{ + VolumeID: "vol-fromsnap", CapacityGiB: 10, State: "available", + SnapshotID: "snap-src", TenantID: "000000000001", + }) + createVolumeInStoreWithMeta(t, svc, store, "vol-othersnap", ebsmetadata.Volume{ + VolumeID: "vol-othersnap", CapacityGiB: 10, State: "available", + SnapshotID: "snap-other", TenantID: "000000000001", + }) + createVolumeInStoreWithMeta(t, svc, store, "vol-blank", ebsmetadata.Volume{ + VolumeID: "vol-blank", CapacityGiB: 10, State: "available", TenantID: "000000000001", + }) + + describe := func(values ...string) []string { + t.Helper() + out, err := svc.DescribeVolumes(context.Background(), &ec2.DescribeVolumesInput{ + Filters: []*ec2.Filter{{Name: aws.String("snapshot-id"), Values: aws.StringSlice(values)}}, + }, "000000000001") + require.NoError(t, err) + ids := make([]string, 0, len(out.Volumes)) + for _, v := range out.Volumes { + ids = append(ids, *v.VolumeId) + } + return ids + } + + assert.Equal(t, []string{"vol-fromsnap"}, describe("snap-src")) + assert.ElementsMatch(t, []string{"vol-fromsnap", "vol-othersnap"}, describe("snap-src", "snap-other")) + assert.Empty(t, describe("snap-unknown")) +} + func TestDescribeVolumes_FilterMultipleValues_OR(t *testing.T) { store := objectstore.NewMemoryObjectStore() svc := newTestVolumeServiceWithStore("ap-southeast-2a", store)