refactor: move aws identifier normalization to foundation

This commit is contained in:
joshsiv-mulga
2026-10-02 13:56:28 +10:00
parent 87a4bb0562
commit 79cf93996f
6 changed files with 54 additions and 42 deletions
@@ -0,0 +1,19 @@
// Package identifiers provides small helpers for AWS resource identifiers.
package identifiers
// Distinct returns the distinct non-nil values of a request's resource-ID
// slice, in request order. A describe that reads one document per named ID must
// not read or report the same resource twice because the request listed it
// twice.
func Distinct(ids []*string) []string {
distinct := make([]string, 0, len(ids))
seen := make(map[string]bool, len(ids))
for _, id := range ids {
if id == nil || seen[*id] {
continue
}
seen[*id] = true
distinct = append(distinct, *id)
}
return distinct
}
@@ -0,0 +1,31 @@
package identifiers
import (
"testing"
"github.com/stretchr/testify/assert"
)
// A describe that reads one document per named ID pays for every entry it is
// given, so a repeated or nil ID has to be dropped before the fan-out and the
// surviving order has to be the request's.
func TestDistinct(t *testing.T) {
first, second := "vol-1", "vol-2"
tests := []struct {
name string
ids []*string
want []string
}{
{name: "nil slice", ids: nil, want: []string{}},
{name: "only nil entries", ids: []*string{nil, nil}, want: []string{}},
{name: "request order", ids: []*string{&second, &first}, want: []string{"vol-2", "vol-1"}},
{name: "duplicates", ids: []*string{&first, &second, &first}, want: []string{"vol-1", "vol-2"}},
{name: "nil among values", ids: []*string{&first, nil, &second}, want: []string{"vol-1", "vol-2"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, Distinct(tt.ids))
})
}
}
+2 -1
View File
@@ -19,6 +19,7 @@ import (
ec2platform "github.com/mulgadc/spinifex/spinifex/domains/ec2/platform"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsfilters "github.com/mulgadc/spinifex/spinifex/foundation/aws/filters"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
handlers_ec2_snapshot "github.com/mulgadc/spinifex/spinifex/handlers/ec2/snapshot"
"github.com/mulgadc/spinifex/spinifex/providers/ebs"
"github.com/mulgadc/spinifex/spinifex/providers/objectstore"
@@ -179,7 +180,7 @@ func (s *ImageServiceImpl) describeImagesByIDs(ctx context.Context, input *ec2.D
parsedFilters map[string][]string, encryptedAtRest bool) (*ec2.DescribeImagesOutput, error) {
// Only nil entries names nothing, which the enumerating path answers with an
// empty result rather than a missing ID.
imageIDs := utils.DistinctIDs(input.ImageIds)
imageIDs := awsidentifiers.Distinct(input.ImageIds)
if len(imageIDs) == 0 {
return &ec2.DescribeImagesOutput{}, nil
}
@@ -21,6 +21,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/domains/ec2/ebs/metadata"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsfilters "github.com/mulgadc/spinifex/spinifex/foundation/aws/filters"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvstore"
"github.com/mulgadc/spinifex/spinifex/foundation/state/migrate"
"github.com/mulgadc/spinifex/spinifex/handlers/ec2/volumestate"
@@ -518,7 +519,7 @@ func (s *SnapshotServiceImpl) describeSnapshotsByIDs(ctx context.Context, input
accountID string, parsedFilters map[string][]string, strict bool) (*ec2.DescribeSnapshotsOutput, error) {
// Only nil entries names nothing, which the listing path answers with an
// empty result rather than a missing ID.
snapshotIDs := utils.DistinctIDs(input.SnapshotIds)
snapshotIDs := awsidentifiers.Distinct(input.SnapshotIds)
if len(snapshotIDs) == 0 {
return &ec2.DescribeSnapshotsOutput{}, nil
}
-16
View File
@@ -37,22 +37,6 @@ func GenerateResourceID(prefix string) string {
return prefix + "-" + hex.EncodeToString(b)[:17]
}
// DistinctIDs returns the distinct non-nil values of a request's resource-ID
// slice, in request order. A describe that reads one document per named ID must
// not read or report the same resource twice because the request listed it twice.
func DistinctIDs(ids []*string) []string {
distinct := make([]string, 0, len(ids))
seen := make(map[string]bool, len(ids))
for _, id := range ids {
if id == nil || seen[*id] {
continue
}
seen[*id] = true
distinct = append(distinct, *id)
}
return distinct
}
func MarshalToXML(payload any) ([]byte, error) {
var buf bytes.Buffer
enc := xml.NewEncoder(&buf)
-24
View File
@@ -26,30 +26,6 @@ import (
"github.com/stretchr/testify/require"
)
// A describe that reads one document per named ID pays for every entry it is
// given, so a repeated or nil ID has to be dropped before the fan-out and the
// surviving order has to be the request's.
func TestDistinctIDs(t *testing.T) {
first, second := "vol-1", "vol-2"
tests := []struct {
name string
ids []*string
want []string
}{
{name: "nil slice", ids: nil, want: []string{}},
{name: "only nil entries", ids: []*string{nil, nil}, want: []string{}},
{name: "request order", ids: []*string{&second, &first}, want: []string{"vol-2", "vol-1"}},
{name: "duplicates", ids: []*string{&first, &second, &first}, want: []string{"vol-1", "vol-2"}},
{name: "nil among values", ids: []*string{&first, nil, &second}, want: []string{"vol-1", "vol-2"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, DistinctIDs(tt.ids))
})
}
}
func TestGenerateResourceID(t *testing.T) {
tests := []struct {
prefix string