refactor: move resource id generation to aws foundation

This commit is contained in:
joshsiv-mulga
2026-10-06 08:44:28 +10:00
parent 3cd8e3c83b
commit 53f13f2137
37 changed files with 174 additions and 143 deletions
+8 -7
View File
@@ -32,6 +32,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/admin"
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
"github.com/mulgadc/spinifex/spinifex/domains/ec2/ebs/metadata"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/foundation/state/clustersize"
handlers_ec2_vpc "github.com/mulgadc/spinifex/spinifex/handlers/ec2/vpc"
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
@@ -778,7 +779,7 @@ func runimagesImportCmd(cmd *cobra.Command, args []string) {
}
// Describe the image/AMI as the control-plane document it will become.
volumeId := utils.GenerateResourceID("ami")
volumeId := awsidentifiers.GenerateResourceID("ami")
amiName := fmt.Sprintf("ami-%s-%s-%s", image.Distro, image.Version, image.Arch)
if amiNameOverride != "" {
amiName = amiNameOverride
@@ -1726,9 +1727,9 @@ func runAdminInit(cmd *cobra.Command, args []string) {
IPSecEnabled: ipsecEnabled,
}
if externalMode != "" {
bootstrapVpcId := utils.GenerateResourceID("vpc")
bootstrapSubnetId := utils.GenerateResourceID("subnet")
bootstrapIgwId := utils.GenerateResourceID("igw")
bootstrapVpcId := awsidentifiers.GenerateResourceID("vpc")
bootstrapSubnetId := awsidentifiers.GenerateResourceID("subnet")
bootstrapIgwId := awsidentifiers.GenerateResourceID("igw")
networkConfig.ExternalMode = externalMode
networkConfig.Pools = externalPools
networkConfig.PoolDNSServers = dnsServers
@@ -1815,9 +1816,9 @@ func runAdminInit(cmd *cobra.Command, args []string) {
// These are written to [bootstrap] in spinifex.toml so vpcd can
// create OVN topology on first boot. The daemon uses the same IDs
// when it creates the records in NATS KV via EnsureDefaultVPC.
bootstrapVpcId := utils.GenerateResourceID("vpc")
bootstrapSubnetId := utils.GenerateResourceID("subnet")
bootstrapIgwId := utils.GenerateResourceID("igw")
bootstrapVpcId := awsidentifiers.GenerateResourceID("vpc")
bootstrapSubnetId := awsidentifiers.GenerateResourceID("subnet")
bootstrapIgwId := awsidentifiers.GenerateResourceID("igw")
configSettings := admin.ConfigSettings{
AccessKey: accessKey,
+2 -1
View File
@@ -21,6 +21,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/admin"
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
"github.com/mulgadc/spinifex/spinifex/domains/ec2/ebs/metadata"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
gateway_bedrock "github.com/mulgadc/spinifex/spinifex/gateway/bedrock"
"github.com/mulgadc/spinifex/spinifex/gateway/bedrock/hfhub"
"github.com/mulgadc/spinifex/spinifex/providers/ebs"
@@ -757,7 +758,7 @@ func runStageWeights(ctx context.Context, store objectstore.ObjectStore, weights
// a live provider -- so it is exercised live rather than in unit tests.
func materializeWeightsVolume(ctx context.Context, provider ebsprovider.EBSProvider, nodeID string, node config.Config, downloadDir string, contentBytes int64) (string, error) {
tmpDir := filepath.Dir(downloadDir)
volumeId := utils.GenerateResourceID("vol")
volumeId := awsidentifiers.GenerateResourceID("vol")
imagePath := filepath.Join(tmpDir, volumeId+".img")
fmt.Println("Building filesystem image ...")
+2 -1
View File
@@ -8,6 +8,7 @@ import (
"strconv"
"time"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
handlers_ochrevector "github.com/mulgadc/spinifex/spinifex/handlers/ochrevector"
"github.com/mulgadc/spinifex/spinifex/utils"
"github.com/pterm/pterm"
@@ -326,7 +327,7 @@ func parseFilterFlag(raw string) (*handlers_ochrevector.Filter, error) {
// creates it. Returns the message to print.
func runIndexCreate(ctx context.Context, svc handlers_ochrevector.VectorService, name string, dimension int, model string) (string, error) {
out, err := svc.CreateIndex(ctx, &handlers_ochrevector.CreateIndexRequest{
IndexID: utils.GenerateResourceID("idx"),
IndexID: awsidentifiers.GenerateResourceID("idx"),
Name: name,
Dimension: dimension,
EmbeddingModel: model,
@@ -8,6 +8,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/mulgadc/spinifex/spinifex/domains/ec2/instancetypes"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/utils"
"github.com/nats-io/nats.go"
)
@@ -44,7 +45,7 @@ func (d *Daemon) handleEC2CreateCapacityReservation(msg *nats.Msg) string {
}
rec := &capacityReservation{
ID: utils.GenerateResourceID("cr"),
ID: awsidentifiers.GenerateResourceID("cr"),
AccountID: accountID,
InstanceType: instanceType,
AvailabilityZone: aws.StringValue(input.AvailabilityZone),
+2 -1
View File
@@ -15,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/mulgadc/spinifex/contracts/ec2/v1"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
handlers_ec2_vpc "github.com/mulgadc/spinifex/spinifex/handlers/ec2/vpc"
handlers_elbv2 "github.com/mulgadc/spinifex/spinifex/handlers/elbv2"
@@ -135,7 +136,7 @@ func (d *Daemon) LaunchSystemInstance(input *handlers_elbv2.SystemInstanceInput)
{Key: aws.String(tags.ManagedByKey), Value: aws.String(tags.ManagedByELBv2)},
}
instance.Reservation = &ec2.Reservation{}
instance.Reservation.SetReservationId(utils.GenerateResourceID("r"))
instance.Reservation.SetReservationId(awsidentifiers.GenerateResourceID("r"))
instance.Reservation.SetOwnerId(accountID)
instance.Reservation.Instances = []*ec2.Instance{ec2Instance}
// Mirror the customer-instance path (handlers/ec2/instance/service_impl.go:334)
@@ -0,0 +1,17 @@
package identifiers
import (
"crypto/rand"
"encoding/hex"
)
// GenerateResourceID generates a unique resource ID with the given prefix.
// Format: {prefix}-{17 hex chars} using crypto/rand.
func GenerateResourceID(prefix string) string {
b := make([]byte, 9)
if _, err := rand.Read(b); err != nil {
//nolint:forbidigo // Continuing after the CSPRNG fails could create predictable resource IDs.
panic("crypto/rand failed: " + err.Error())
}
return prefix + "-" + hex.EncodeToString(b)[:17]
}
@@ -0,0 +1,35 @@
package identifiers
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGenerateResourceID(t *testing.T) {
tests := []struct {
prefix string
}{
{"i"},
{"r"},
{"vol"},
{"snap"},
{"key"},
{"eigw"},
{"ami"},
}
for _, tt := range tests {
t.Run(tt.prefix, func(t *testing.T) {
id := GenerateResourceID(tt.prefix)
assert.True(t, strings.HasPrefix(id, tt.prefix+"-"))
// prefix + "-" + 17 hex chars
assert.Len(t, id, len(tt.prefix)+1+17)
// Verify uniqueness
id2 := GenerateResourceID(tt.prefix)
assert.NotEqual(t, id, id2)
})
}
}
@@ -13,6 +13,7 @@ import (
"github.com/mulgadc/spinifex/contracts/ec2/v1"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/arn"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
"github.com/mulgadc/spinifex/spinifex/utils"
"github.com/nats-io/nats.go"
@@ -686,7 +687,7 @@ func TestCountInstanceProfileAssociations_NoMatches(t *testing.T) {
// utils generator would break replay parsing of Disassociate/Replace.
func TestAssociationIDFormat(t *testing.T) {
t.Parallel()
id := utils.GenerateResourceID("iip-assoc")
id := awsidentifiers.GenerateResourceID("iip-assoc")
assert.True(t, strings.HasPrefix(id, "iip-assoc-"),
"GenerateResourceID must preserve the AWS-style hyphen between prefix and suffix")
suffix := strings.TrimPrefix(id, "iip-assoc-")
+3 -2
View File
@@ -15,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
clusterv1 "github.com/mulgadc/spinifex/contracts/cluster/v1"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
handlers_ec2_placementgroup "github.com/mulgadc/spinifex/spinifex/handlers/ec2/placementgroup"
"github.com/mulgadc/spinifex/spinifex/utils"
@@ -57,7 +58,7 @@ func distributeInstances(ctx context.Context, input *ec2.RunInstancesInput, nats
allocations := spreadAllocate(nodes, launchCount)
// Minted once here and handed to every node, so a launch that spreads
// across nodes comes back as one reservation instead of one per node.
reservationID := utils.GenerateResourceID("r")
reservationID := awsidentifiers.GenerateResourceID("r")
results := launchOnNodes(ctx, allocations, input, natsConn, accountID, reservationID)
return aggregateResults(ctx, results, minCount, natsConn, accountID)
}
@@ -281,7 +282,7 @@ func distributeInstancesSpread(ctx context.Context, input *ec2.RunInstancesInput
// A spread group puts one instance on each node, so without a shared ID
// every node mints its own and one launch comes back as several
// reservations.
spreadReservationID := utils.GenerateResourceID("r")
spreadReservationID := awsidentifiers.GenerateResourceID("r")
results := launchOnNodes(ctx, allocations, input, natsConn, accountID, spreadReservationID)
var allInstances []*ec2.Instance
@@ -15,12 +15,12 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
gateway_ec2_instance "github.com/mulgadc/spinifex/spinifex/gateway/ec2/instance"
handlers_ec2_spotinstance "github.com/mulgadc/spinifex/spinifex/handlers/ec2/spotinstance"
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
handlers_quota "github.com/mulgadc/spinifex/spinifex/handlers/quota"
"github.com/mulgadc/spinifex/spinifex/utils"
"github.com/nats-io/nats.go"
)
@@ -192,7 +192,7 @@ func buildSpotRequests(input *ec2.RequestSpotInstancesInput, runInput *ec2.RunIn
requests := make([]*ec2.SpotInstanceRequest, 0, count)
for range count {
req := &ec2.SpotInstanceRequest{
SpotInstanceRequestId: aws.String(utils.GenerateResourceID("sir")),
SpotInstanceRequestId: aws.String(awsidentifiers.GenerateResourceID("sir")),
State: aws.String(ec2.SpotInstanceStateActive),
Type: aws.String(spotType),
ProductDescription: aws.String(ec2.RIProductDescriptionLinuxUnix),
+2 -1
View File
@@ -15,6 +15,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
"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"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
"github.com/mulgadc/spinifex/spinifex/foundation/state/migrate"
@@ -94,7 +95,7 @@ func (s *EgressOnlyIGWServiceImpl) CreateEgressOnlyInternetGateway(ctx context.C
return nil, awserrors.IDNotFound(awserrors.ErrorInvalidVpcIDNotFound, "vpc", *input.VpcId)
}
eigwID := utils.GenerateResourceID("eigw")
eigwID := awsidentifiers.GenerateResourceID("eigw")
record := EgressOnlyIGWRecord{
EgressOnlyInternetGatewayId: eigwID,
+3 -2
View File
@@ -13,6 +13,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"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"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
"github.com/mulgadc/spinifex/spinifex/foundation/state/migrate"
@@ -109,7 +110,7 @@ func (s *EIPServiceImpl) AllocateAddress(ctx context.Context, input *ec2.Allocat
}
func (s *EIPServiceImpl) allocateAddress(ctx context.Context, input *ec2.AllocateAddressInput, accountID string) (*ec2.AllocateAddressOutput, error) {
allocID := utils.GenerateResourceID("eipalloc")
allocID := awsidentifiers.GenerateResourceID("eipalloc")
var publicIP, poolName string
var err error
@@ -256,7 +257,7 @@ func (s *EIPServiceImpl) AssociateAddress(ctx context.Context, input *ec2.Associ
privateIP = *input.PrivateIpAddress
}
associationID := utils.GenerateResourceID("eipassoc")
associationID := awsidentifiers.GenerateResourceID("eipassoc")
record.AssociationId = associationID
record.ENIId = eniID
+2 -1
View File
@@ -15,6 +15,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
"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/aws/paging"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
@@ -115,7 +116,7 @@ func NewIGWServiceImplWithNATS(ctx context.Context, cfg *config.Config, natsConn
// CreateInternetGateway creates a new Internet Gateway (initially detached).
func (s *IGWServiceImpl) CreateInternetGateway(ctx context.Context, input *ec2.CreateInternetGatewayInput, accountID string) (*ec2.CreateInternetGatewayOutput, error) {
igwID := utils.GenerateResourceID("igw")
igwID := awsidentifiers.GenerateResourceID("igw")
return s.createIGW(ctx, input, accountID, igwID)
}
+5 -5
View File
@@ -434,8 +434,8 @@ func (s *ImageServiceImpl) CreateImageFromInstance(params CreateImageParams, acc
}
}
amiID := utils.GenerateResourceID("ami")
snapshotID := utils.GenerateResourceID("snap")
amiID := awsidentifiers.GenerateResourceID("ami")
snapshotID := awsidentifiers.GenerateResourceID("snap")
slog.Info("CreateImageFromInstance", "instanceId", *input.InstanceId,
"rootVolumeId", params.RootVolumeID, "amiId", amiID, "snapshotId", snapshotID,
@@ -862,8 +862,8 @@ func (s *ImageServiceImpl) CopyImage(ctx context.Context, input *ec2.CopyImageIn
return nil, errors.New(awserrors.ErrorInvalidAMINameDuplicate)
}
newSnapshotID := utils.GenerateResourceID("snap")
newImageID := utils.GenerateResourceID("ami")
newSnapshotID := awsidentifiers.GenerateResourceID("snap")
newImageID := awsidentifiers.GenerateResourceID("ami")
// New snap shares source VolumeID — no block copy.
snapSizeGiB := uint64(0)
@@ -1092,7 +1092,7 @@ func (s *ImageServiceImpl) RegisterImage(ctx context.Context, input *ec2.Registe
tags := awstags.Extract(input.TagSpecifications, "image")
amiID := utils.GenerateResourceID("ami")
amiID := awsidentifiers.GenerateResourceID("ami")
meta := ebsmetadata.AMI{
ImageID: amiID,
Name: name,
@@ -27,6 +27,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"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvstore"
handlers_dns "github.com/mulgadc/spinifex/spinifex/handlers/dns"
handlers_ec2_vpc "github.com/mulgadc/spinifex/spinifex/handlers/ec2/vpc"
@@ -206,7 +207,7 @@ func parseVolumeParams(input *ec2.RunInstancesInput) volumeParams {
}
if strings.HasPrefix(*input.ImageId, "ami-") {
p.imageId = utils.GenerateResourceID("vol")
p.imageId = awsidentifiers.GenerateResourceID("vol")
p.snapshotId = *input.ImageId
} else {
p.imageId = *input.ImageId
@@ -326,7 +327,7 @@ func (s *InstanceServiceImpl) RunInstance(input *ec2.RunInstancesInput) (*vm.VM,
return nil, nil, errors.New(awserrors.ErrorInvalidInstanceType)
}
instanceId := utils.GenerateResourceID("i")
instanceId := awsidentifiers.GenerateResourceID("i")
// Create new instance structure
instance := &vm.VM{
@@ -382,7 +383,7 @@ func (s *InstanceServiceImpl) RunInstance(input *ec2.RunInstancesInput) (*vm.VM,
arn := aws.StringValue(input.IamInstanceProfile.Arn)
if arn != "" {
instance.IamInstanceProfileArn = arn
instance.IamInstanceProfileAssociationId = utils.GenerateResourceID("iip-assoc")
instance.IamInstanceProfileAssociationId = awsidentifiers.GenerateResourceID("iip-assoc")
ec2Instance.IamInstanceProfile = &ec2.IamInstanceProfile{
Arn: aws.String(arn),
}
@@ -987,7 +988,7 @@ func (s *InstanceServiceImpl) PrepareRunInstances(ctx context.Context, input *ec
}
reservation := &ec2.Reservation{}
reservation.SetReservationId(utils.GenerateResourceID("r"))
reservation.SetReservationId(awsidentifiers.GenerateResourceID("r"))
reservation.SetOwnerId(accountID)
reservation.Instances = allEC2Instances
@@ -1346,7 +1347,7 @@ func (s *InstanceServiceImpl) AssociateIamInstanceProfile(ctx context.Context, i
return nil, errors.New(awserrors.ErrorMissingParameter)
}
profileArn := command.IamProfileAssociationData.InstanceProfileArn
newID := utils.GenerateResourceID("iip-assoc")
newID := awsidentifiers.GenerateResourceID("iip-assoc")
timestamp := time.Now().UTC()
var alreadyAssociated bool
@@ -1441,7 +1442,7 @@ func (s *InstanceServiceImpl) ReplaceIamProfileAssociation(ctx context.Context,
return nil, nil
}
newID := utils.GenerateResourceID("iip-assoc")
newID := awsidentifiers.GenerateResourceID("iip-assoc")
timestamp := time.Now().UTC()
var swapped bool
_, err := s.vmMgr.UpdateAndPersist(owner, func(v *vm.VM) bool {
+3 -2
View File
@@ -28,6 +28,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
"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"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/providers/objectstore"
"github.com/mulgadc/spinifex/spinifex/utils"
@@ -210,7 +211,7 @@ func (s *KeyServiceImpl) CreateKeyPair(ctx context.Context, input *ec2.CreateKey
}
// Build response (similar to AWS EC2)
keyPairID := utils.GenerateResourceID("key")
keyPairID := awsidentifiers.GenerateResourceID("key")
tagMap := awstags.Extract(input.TagSpecifications, "key-pair")
tags := awstags.MapToEC2(tagMap)
// AWS ends RSA material at its END line, while OpenSSH-format Ed25519
@@ -986,7 +987,7 @@ func (s *KeyServiceImpl) ImportKeyPair(ctx context.Context, input *ec2.ImportKey
}
// Generate key pair ID
keyPairID := utils.GenerateResourceID("key")
keyPairID := awsidentifiers.GenerateResourceID("key")
// Build response output
tagMap := awstags.Extract(input.TagSpecifications, "key-pair")
@@ -17,10 +17,10 @@ import (
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
"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"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
"github.com/mulgadc/spinifex/spinifex/foundation/state/migrate"
"github.com/mulgadc/spinifex/spinifex/utils"
"github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/jetstream"
)
@@ -277,7 +277,7 @@ func (s *LaunchTemplateServiceImpl) CreateLaunchTemplate(ctx context.Context, in
return nil, errors.New(awserrors.ErrorInvalidParameterValue)
}
ltID := utils.GenerateResourceID("lt")
ltID := awsidentifiers.GenerateResourceID("lt")
if err := s.claimName(ctx, accountID, name, ltID); err != nil {
return nil, err
}
+3 -2
View File
@@ -13,6 +13,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"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"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
"github.com/mulgadc/spinifex/spinifex/foundation/state/migrate"
@@ -140,7 +141,7 @@ func (s *NatGatewayServiceImpl) CreateNatGateway(ctx context.Context, input *ec2
return nil, errors.New(awserrors.ErrorResourceAlreadyAssociated)
}
natgwID := utils.GenerateResourceID("nat")
natgwID := awsidentifiers.GenerateResourceID("nat")
record := NatGatewayRecord{
NatGatewayId: natgwID,
VpcId: subnetRecord.VpcId,
@@ -166,7 +167,7 @@ func (s *NatGatewayServiceImpl) CreateNatGateway(ctx context.Context, input *ec2
// NAT GW reusing the same allocation). Linkage is the shared AllocationId;
// DeleteNatGateway clears it back to allocated. Non-fatal: the NAT GW is
// already stored, so a failed mark only weakens the reuse guard until then.
eipRecord.AssociationId = utils.GenerateResourceID("eipassoc")
eipRecord.AssociationId = awsidentifiers.GenerateResourceID("eipassoc")
eipRecord.VpcId = subnetRecord.VpcId
eipRecord.State = "associated"
if eipData, err := json.Marshal(eipRecord); err == nil {
@@ -15,10 +15,10 @@ import (
"github.com/mulgadc/spinifex/spinifex/foundation/aws/arn"
"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"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
"github.com/mulgadc/spinifex/spinifex/foundation/state/migrate"
"github.com/mulgadc/spinifex/spinifex/utils"
"github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/jetstream"
)
@@ -112,7 +112,7 @@ func (s *PlacementGroupServiceImpl) CreatePlacementGroup(ctx context.Context, in
groupName := *input.GroupName
key := kvutil.AccountKey(accountID, groupName)
groupID := utils.GenerateResourceID("pg")
groupID := awsidentifiers.GenerateResourceID("pg")
record := PlacementGroupRecord{
GroupId: groupID,
@@ -16,6 +16,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/bootstrap/config"
"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/aws/paging"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
@@ -489,7 +490,7 @@ func (s *RouteTableServiceImpl) allRouteTablesForVPC(ctx context.Context, accoun
// Exported for use by VPC service when creating default VPCs.
func (s *RouteTableServiceImpl) CreateRouteTableForVPC(vpcID, vpcCidr, accountID string, isMain bool, rtbID string) (*RouteTableRecord, error) {
if rtbID == "" {
rtbID = utils.GenerateResourceID("rtb")
rtbID = awsidentifiers.GenerateResourceID("rtb")
}
record := RouteTableRecord{
@@ -512,7 +513,7 @@ func (s *RouteTableServiceImpl) CreateRouteTableForVPC(vpcID, vpcCidr, accountID
if isMain {
record.Associations = []AssociationRecord{
{
AssociationId: utils.GenerateResourceID("rtbassoc"),
AssociationId: awsidentifiers.GenerateResourceID("rtbassoc"),
Main: true,
},
}
@@ -1020,7 +1021,7 @@ func (s *RouteTableServiceImpl) AssociateRouteTable(ctx context.Context, input *
}
}
assocID := utils.GenerateResourceID("rtbassoc")
assocID := awsidentifiers.GenerateResourceID("rtbassoc")
if err := s.mutateRouteTableCAS(ctx, accountID, rtbID, func(rec *RouteTableRecord) (bool, error) {
// Re-check same-table association under the fresh read: a concurrent
// associate for this subnet may have landed since the precheck.
@@ -1224,7 +1225,7 @@ func (s *RouteTableServiceImpl) ReplaceRouteTableAssociation(ctx context.Context
s.publishIGWRouteEventsForAssociation(ctx, accountID, "vpc.delete-igw-route", &oldRecord, assoc.SubnetId)
// Add to new table with new ID
newAssocID := utils.GenerateResourceID("rtbassoc")
newAssocID := awsidentifiers.GenerateResourceID("rtbassoc")
newRecord.Associations = append(newRecord.Associations, AssociationRecord{
AssociationId: newAssocID,
SubnetId: assoc.SubnetId,
@@ -188,7 +188,7 @@ func (s *SnapshotServiceImpl) CreateSnapshot(ctx context.Context, input *ec2.Cre
slog.InfoContext(ctx, "CreateSnapshot request", "volumeId", volumeID)
snapshotID := utils.GenerateResourceID("snap")
snapshotID := awsidentifiers.GenerateResourceID("snap")
if s.provider == nil {
slog.ErrorContext(ctx, "no EBS provider configured", "op", "CreateSnapshot")
return nil, errors.New(awserrors.ErrorServerInternal)
@@ -822,7 +822,7 @@ func (s *SnapshotServiceImpl) CopySnapshot(ctx context.Context, input *ec2.CopyS
return nil, errors.New(awserrors.ErrorUnsupportedOperation)
}
newSnapshotID := utils.GenerateResourceID("snap")
newSnapshotID := awsidentifiers.GenerateResourceID("snap")
copied, err := s.provider.CopySnapshot(ctx, ebsprovider.CopySnapshotRequest{
Versioned: ebsprovider.NewVersioned(),
SourceSnapshotID: sourceSnapshotID,
+2 -1
View File
@@ -21,6 +21,7 @@ import (
ebspolicy "github.com/mulgadc/spinifex/spinifex/domains/ec2/ebs/policy"
"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"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
handlers_ec2_instance "github.com/mulgadc/spinifex/spinifex/handlers/ec2/instance"
"github.com/mulgadc/spinifex/spinifex/providers/ebs"
@@ -177,7 +178,7 @@ func (s *VolumeServiceImpl) CreateVolume(ctx context.Context, input *ec2.CreateV
}
now := time.Now()
volumeID := utils.GenerateResourceID("vol")
volumeID := awsidentifiers.GenerateResourceID("vol")
// Honor caller-supplied Iops for gp3, else the 3000 baseline. The ceiling is
// min(16000, 500*size) but never below the free baseline, so small volumes
@@ -603,7 +603,7 @@ func TestApplyRecordTags_Provider_VisibleViaDescribeVolumes(t *testing.T) {
// prefixFailingObjectStore fails PutObject for any key under failPrefix and
// records the last such key, so a test can recover a randomly generated
// resource ID from the write CreateVolume/CreateSnapshot attempted, without
// needing to predict utils.GenerateResourceID's output up front.
// needing to predict awsidentifiers.GenerateResourceID's output up front.
type prefixFailingObjectStore struct {
objectstore.ObjectStore
+7 -7
View File
@@ -10,8 +10,8 @@ import (
"strings"
"time"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
"github.com/mulgadc/spinifex/spinifex/utils"
"github.com/nats-io/nats.go/jetstream"
)
@@ -161,11 +161,11 @@ func (s *VPCServiceImpl) proposeDefaultVPC(ctx context.Context, accountID string
return fmt.Errorf("allocate VNI for default VPC: %w", err)
}
claim = &defaultVPCClaim{
VpcId: cmp.Or(ids.VpcId, utils.GenerateResourceID("vpc")),
SubnetId: cmp.Or(ids.SubnetId, utils.GenerateResourceID("subnet")),
GroupId: utils.GenerateResourceID("sg"),
RouteTableId: utils.GenerateResourceID("rtb"),
InternetGatewayId: cmp.Or(ids.IgwId, utils.GenerateResourceID("igw")),
VpcId: cmp.Or(ids.VpcId, awsidentifiers.GenerateResourceID("vpc")),
SubnetId: cmp.Or(ids.SubnetId, awsidentifiers.GenerateResourceID("subnet")),
GroupId: awsidentifiers.GenerateResourceID("sg"),
RouteTableId: awsidentifiers.GenerateResourceID("rtb"),
InternetGatewayId: cmp.Or(ids.IgwId, awsidentifiers.GenerateResourceID("igw")),
Cidr: DefaultVPCCidr,
SubnetCidr: DefaultSubnetCidr,
VNI: vni,
@@ -202,7 +202,7 @@ func (s *VPCServiceImpl) adoptExistingDefaultVPC(ctx context.Context, accountID
claim := &defaultVPCClaim{
VpcId: vpc.VpcId,
InternetGatewayId: cmp.Or(ids.IgwId, utils.GenerateResourceID("igw")),
InternetGatewayId: cmp.Or(ids.IgwId, awsidentifiers.GenerateResourceID("igw")),
Cidr: vpc.CidrBlock,
VNI: vpc.VNI,
Complete: true,
+3 -2
View File
@@ -15,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"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/aws/paging"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
@@ -143,7 +144,7 @@ func (s *VPCServiceImpl) CreateNetworkInterface(ctx context.Context, input *ec2.
return nil, err
}
eniId := utils.GenerateResourceID("eni")
eniId := awsidentifiers.GenerateResourceID("eni")
// Allocate IP from subnet, or claim the caller's requested address.
var privateIP string
@@ -711,7 +712,7 @@ func (s *VPCServiceImpl) attachENI(ctx context.Context, accountID, eniId, instan
return "", errors.New(awserrors.ErrorInvalidNetworkInterfaceInUse)
}
attachmentId := utils.GenerateResourceID("eni-attach")
attachmentId := awsidentifiers.GenerateResourceID("eni-attach")
record.Status = "in-use"
record.AttachmentId = attachmentId
record.InstanceId = instanceId
+11 -10
View File
@@ -18,6 +18,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"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/aws/paging"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
@@ -25,10 +26,10 @@ import (
"github.com/nats-io/nats.go/jetstream"
)
// sgIDRegex must stay in lockstep with utils.GenerateResourceID("sg").
// sgIDRegex must stay in lockstep with awsidentifiers.GenerateResourceID("sg").
var sgIDRegex = regexp.MustCompile(`^sg-[0-9a-f]{17}$`)
// SGRuleIDRegex must stay in lockstep with utils.GenerateResourceID("sgr").
// SGRuleIDRegex must stay in lockstep with awsidentifiers.GenerateResourceID("sgr").
// Exported so the EC2 gateway can validate SecurityGroupRuleIds without
// re-implementing the format check.
var SGRuleIDRegex = regexp.MustCompile(`^sgr-[0-9a-f]{17}$`)
@@ -241,7 +242,7 @@ func (s *VPCServiceImpl) CreateSecurityGroup(ctx context.Context, input *ec2.Cre
return nil, errors.New(awserrors.ErrorResourceLimitExceeded)
}
groupId := utils.GenerateResourceID("sg")
groupId := awsidentifiers.GenerateResourceID("sg")
description := ""
if input.Description != nil {
@@ -250,7 +251,7 @@ func (s *VPCServiceImpl) CreateSecurityGroup(ctx context.Context, input *ec2.Cre
// Default egress rule: allow all outbound traffic
defaultEgress := []SGRule{
{RuleId: utils.GenerateResourceID("sgr"), IpProtocol: "-1", FromPort: 0, ToPort: 0, CidrIp: "0.0.0.0/0"},
{RuleId: awsidentifiers.GenerateResourceID("sgr"), IpProtocol: "-1", FromPort: 0, ToPort: 0, CidrIp: "0.0.0.0/0"},
}
record := SecurityGroupRecord{
@@ -1942,7 +1943,7 @@ func ipPermissionsToSGRules(perms []*ec2.IpPermission, mode sgParseMode) ([]SGRu
return nil, err
}
if mode == sgParseAuthorize {
r.RuleId = utils.GenerateResourceID("sgr")
r.RuleId = awsidentifiers.GenerateResourceID("sgr")
}
rules = append(rules, r)
appended = true
@@ -1960,7 +1961,7 @@ func ipPermissionsToSGRules(perms []*ec2.IpPermission, mode sgParseMode) ([]SGRu
return nil, err
}
if mode == sgParseAuthorize {
r.RuleId = utils.GenerateResourceID("sgr")
r.RuleId = awsidentifiers.GenerateResourceID("sgr")
}
rules = append(rules, r)
appended = true
@@ -1978,7 +1979,7 @@ func ipPermissionsToSGRules(perms []*ec2.IpPermission, mode sgParseMode) ([]SGRu
return nil, err
}
if mode == sgParseAuthorize {
r.RuleId = utils.GenerateResourceID("sgr")
r.RuleId = awsidentifiers.GenerateResourceID("sgr")
}
rules = append(rules, r)
appended = true
@@ -2153,7 +2154,7 @@ func (s *VPCServiceImpl) requestSGEvent(topic string, evt SGEvent) error {
// AWS-equivalent rules, bypassing the public-API reserved-name guard. Used by
// CreateVpc.
func (s *VPCServiceImpl) createDefaultSecurityGroupInternal(ctx context.Context, accountID, vpcId string) (string, error) {
record, _, err := s.storeDefaultSecurityGroup(ctx, accountID, vpcId, utils.GenerateResourceID("sg"))
record, _, err := s.storeDefaultSecurityGroup(ctx, accountID, vpcId, awsidentifiers.GenerateResourceID("sg"))
if err != nil {
return "", err
}
@@ -2172,10 +2173,10 @@ func (s *VPCServiceImpl) storeDefaultSecurityGroup(ctx context.Context, accountI
Description: defaultSecurityGroupDescription,
VpcId: vpcId,
IngressRules: []SGRule{
{RuleId: utils.GenerateResourceID("sgr"), IpProtocol: "-1", FromPort: 0, ToPort: 0, SourceSG: groupId},
{RuleId: awsidentifiers.GenerateResourceID("sgr"), IpProtocol: "-1", FromPort: 0, ToPort: 0, SourceSG: groupId},
},
EgressRules: []SGRule{
{RuleId: utils.GenerateResourceID("sgr"), IpProtocol: "-1", FromPort: 0, ToPort: 0, CidrIp: "0.0.0.0/0"},
{RuleId: awsidentifiers.GenerateResourceID("sgr"), IpProtocol: "-1", FromPort: 0, ToPort: 0, CidrIp: "0.0.0.0/0"},
},
Tags: map[string]string{},
IsDefault: true,
+5 -4
View File
@@ -17,6 +17,7 @@ import (
"github.com/mulgadc/spinifex/spinifex/foundation/aws/arn"
"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/aws/paging"
awstags "github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvutil"
@@ -296,7 +297,7 @@ func (s *VPCServiceImpl) CreateVpc(ctx context.Context, input *ec2.CreateVpcInpu
return nil, errors.New(awserrors.ErrorServerInternal)
}
vpcID := utils.GenerateResourceID("vpc")
vpcID := awsidentifiers.GenerateResourceID("vpc")
record := VPCRecord{
VpcId: vpcID,
@@ -778,7 +779,7 @@ func (s *VPCServiceImpl) CreateSubnet(ctx context.Context, input *ec2.CreateSubn
az = s.config.AZ
}
subnetID := utils.GenerateResourceID("subnet")
subnetID := awsidentifiers.GenerateResourceID("subnet")
// Calculate available IPs (total hosts minus AWS reserved: network, router, DNS, future, broadcast)
// ones is validated to be 16-28 above, so (32-ones) is always 4-16 and safe for uint conversion
@@ -1497,7 +1498,7 @@ func (s *VPCServiceImpl) createMainRouteTable(ctx context.Context, accountID, vp
"routeTableId", existing, "vpcId", vpcID, "accountID", accountID)
return nil
}
_, err := s.writeMainRouteTable(ctx, accountID, vpcID, vpcCidr, utils.GenerateResourceID("rtb"))
_, err := s.writeMainRouteTable(ctx, accountID, vpcID, vpcCidr, awsidentifiers.GenerateResourceID("rtb"))
return err
}
@@ -1540,7 +1541,7 @@ func (s *VPCServiceImpl) writeMainRouteTable(ctx context.Context, accountID, vpc
AssociationId string `json:"association_id"`
Main bool `json:"main"`
}{
{AssociationId: utils.GenerateResourceID("rtbassoc"), Main: true},
{AssociationId: awsidentifiers.GenerateResourceID("rtbassoc"), Main: true},
},
Tags: make(map[string]string),
CreatedAt: time.Now(),
+4 -3
View File
@@ -23,6 +23,7 @@ import (
acmdomain "github.com/mulgadc/spinifex/spinifex/domains/acm"
resourcearn "github.com/mulgadc/spinifex/spinifex/foundation/aws/arn"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/tags"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvstore"
handlers_dns "github.com/mulgadc/spinifex/spinifex/handlers/dns"
@@ -1296,7 +1297,7 @@ func (s *ELBv2ServiceImpl) createLoadBalancer(ctx context.Context, input *elbv2.
}
}
lbID := utils.GenerateResourceID("lb")
lbID := awsidentifiers.GenerateResourceID("lb")
lbArn := resourcearn.FormatELBv2LoadBalancer(s.region, accountID, name, lbID, lbType)
arnPathSegment := resourcearn.ELBv2LBPathSegment(lbType)
dnsPrefix := ""
@@ -1982,7 +1983,7 @@ func (s *ELBv2ServiceImpl) CreateTargetGroup(ctx context.Context, input *elbv2.C
hc.Matcher = *input.Matcher.HttpCode
}
tgID := utils.GenerateResourceID("tg")
tgID := awsidentifiers.GenerateResourceID("tg")
tgArn := resourcearn.FormatELBv2TargetGroup(s.region, accountID, name, tgID)
tags := tagsFromSDK(input.Tags)
@@ -2669,7 +2670,7 @@ func (s *ELBv2ServiceImpl) CreateListener(ctx context.Context, input *elbv2.Crea
return nil, err
}
listenerID := utils.GenerateResourceID("lst")
listenerID := awsidentifiers.GenerateResourceID("lst")
listenerArn := resourcearn.FormatELBv2Listener(s.region, accountID, lb.Name, lb.LoadBalancerID, listenerID, lb.Type)
var actions []ListenerAction
@@ -14,7 +14,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
"github.com/mulgadc/spinifex/spinifex/utils"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
)
// Regex guards for rule condition values — rejected at write time so the renderer
@@ -78,7 +78,7 @@ func (s *ELBv2ServiceImpl) CreateRule(ctx context.Context, input *elbv2.CreateRu
}
}
ruleID := utils.GenerateResourceID("rule")
ruleID := awsidentifiers.GenerateResourceID("rule")
ruleArn, err := buildRuleArn(listener.ListenerArn, ruleID)
if err != nil {
slog.ErrorContext(ctx, "CreateRule: failed to build ARN", "listenerArn", listener.ListenerArn, "err", err)
+1 -1
View File
@@ -9,7 +9,7 @@ import (
)
// indexIDPattern is a conservative allowlist for anything that reaches a SQL
// identifier: utils.GenerateResourceID's own alphabet ("idx-<17 hex>") plus
// identifier: awsidentifiers.GenerateResourceID's own alphabet ("idx-<17 hex>") plus
// enough headroom that a caller-supplied id still round-trips safely rather
// than being silently rejected.
var indexIDPattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}$`)
+2 -2
View File
@@ -11,8 +11,8 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/providers/objectstore"
"github.com/mulgadc/spinifex/spinifex/utils"
)
// Embedder is the local seam for batch text embedding: the same method set
@@ -127,7 +127,7 @@ func (s *IngestService) StartIngest(ctx context.Context, accountID, indexID stri
now := time.Now().UTC()
rec := JobRecord{
ID: utils.GenerateResourceID("job"),
ID: awsidentifiers.GenerateResourceID("job"),
IndexID: indexID,
DataSourceID: dataSourceID,
Source: source,
+2 -2
View File
@@ -10,9 +10,9 @@ import (
"time"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvstore"
handlers_iam "github.com/mulgadc/spinifex/spinifex/handlers/iam"
"github.com/mulgadc/spinifex/spinifex/utils"
)
// The staged master password is encrypted at rest under bootstrap-payloads/{id}
@@ -86,7 +86,7 @@ func (s *Service) writeBootstrapPayload(ctx context.Context, kv *kvstore.Bucket,
return "", err
}
keyID := bootstrapKeyID(key)
payloadID := utils.GenerateResourceID(bootstrapPayloadIDPrefix)
payloadID := awsidentifiers.GenerateResourceID(bootstrapPayloadIDPrefix)
plaintext, err := json.Marshal(bootstrapPayloadClaims{
EnvelopeVersion: bootstrapEnvelopeVersion,
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"github.com/aws/aws-sdk-go/service/rds"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/foundation/state/kvstore"
"github.com/mulgadc/spinifex/spinifex/runtime/compute/vm"
"github.com/mulgadc/spinifex/spinifex/utils"
@@ -150,7 +151,7 @@ func newDBInstanceRecord(accountID string, req *validatedCreate, placement *endp
now := time.Now().UTC()
return DBInstanceRecord{
DBInstanceIdentifier: req.Identifier,
DbiResourceID: utils.GenerateResourceID(dbiResourceIDPrefix),
DbiResourceID: awsidentifiers.GenerateResourceID(dbiResourceIDPrefix),
AccountID: accountID,
Status: StatusCreating,
VMGeneration: firstVMGeneration,
+19 -19
View File
@@ -8,9 +8,9 @@ import (
"slices"
"sync"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/network/ovn"
"github.com/mulgadc/spinifex/spinifex/network/ovn/nbdb"
"github.com/mulgadc/spinifex/spinifex/utils"
)
// Client implements ovn.Client with in-memory storage for testing.
@@ -95,7 +95,7 @@ func (m *Client) CreateLogicalSwitch(_ context.Context, ls *nbdb.LogicalSwitch)
return fmt.Errorf("logical switch %q already exists", ls.Name)
}
if ls.UUID == "" {
ls.UUID = utils.GenerateResourceID("ovn")
ls.UUID = awsidentifiers.GenerateResourceID("ovn")
}
stored := *ls
m.Switches[ls.Name] = &stored
@@ -112,7 +112,7 @@ func (m *Client) EnsureLogicalSwitch(_ context.Context, ls *nbdb.LogicalSwitch)
return &result, false, nil
}
if ls.UUID == "" {
ls.UUID = utils.GenerateResourceID("ovn")
ls.UUID = awsidentifiers.GenerateResourceID("ovn")
}
stored := *ls
m.Switches[ls.Name] = &stored
@@ -164,7 +164,7 @@ func (m *Client) CreateLogicalSwitchPort(_ context.Context, switchName string, l
return fmt.Errorf("logical switch port %q already exists", lsp.Name)
}
if lsp.UUID == "" {
lsp.UUID = utils.GenerateResourceID("ovn")
lsp.UUID = awsidentifiers.GenerateResourceID("ovn")
}
stored := *lsp
m.Ports[lsp.Name] = &stored
@@ -192,7 +192,7 @@ func (m *Client) CreateLogicalSwitchPortInGroups(_ context.Context, switchName s
}
}
if lsp.UUID == "" {
lsp.UUID = utils.GenerateResourceID("ovn")
lsp.UUID = awsidentifiers.GenerateResourceID("ovn")
}
stored := *lsp
m.Ports[lsp.Name] = &stored
@@ -276,7 +276,7 @@ func (m *Client) CreateLogicalRouter(_ context.Context, lr *nbdb.LogicalRouter)
return fmt.Errorf("logical router %q already exists", lr.Name)
}
if lr.UUID == "" {
lr.UUID = utils.GenerateResourceID("ovn")
lr.UUID = awsidentifiers.GenerateResourceID("ovn")
}
stored := *lr
m.Routers[lr.Name] = &stored
@@ -293,7 +293,7 @@ func (m *Client) EnsureLogicalRouter(_ context.Context, lr *nbdb.LogicalRouter)
return &result, false, nil
}
if lr.UUID == "" {
lr.UUID = utils.GenerateResourceID("ovn")
lr.UUID = awsidentifiers.GenerateResourceID("ovn")
}
stored := *lr
m.Routers[lr.Name] = &stored
@@ -357,7 +357,7 @@ func (m *Client) CreateLogicalRouterPort(_ context.Context, routerName string, l
return fmt.Errorf("logical router port %q already exists", lrp.Name)
}
if lrp.UUID == "" {
lrp.UUID = utils.GenerateResourceID("ovn")
lrp.UUID = awsidentifiers.GenerateResourceID("ovn")
}
stored := *lrp
m.RouterPorts[lrp.Name] = &stored
@@ -415,7 +415,7 @@ func (m *Client) CreateDHCPOptions(_ context.Context, opts *nbdb.DHCPOptions) (s
m.Mu.Lock()
defer m.Mu.Unlock()
if opts.UUID == "" {
opts.UUID = utils.GenerateResourceID("dhcp")
opts.UUID = awsidentifiers.GenerateResourceID("dhcp")
}
stored := *opts
m.DHCPOpts[opts.UUID] = &stored
@@ -487,7 +487,7 @@ func (m *Client) AddNAT(_ context.Context, routerName string, nat *nbdb.NAT) err
return fmt.Errorf("logical router %q not found", routerName)
}
if nat.UUID == "" {
nat.UUID = utils.GenerateResourceID("nat")
nat.UUID = awsidentifiers.GenerateResourceID("nat")
}
stored := *nat
m.NATs[nat.UUID] = &stored
@@ -676,7 +676,7 @@ func (m *Client) AddStaticRoute(_ context.Context, routerName string, route *nbd
return fmt.Errorf("logical router %q not found", routerName)
}
if route.UUID == "" {
route.UUID = utils.GenerateResourceID("route")
route.UUID = awsidentifiers.GenerateResourceID("route")
}
stored := *route
m.StaticRoutes[route.UUID] = &stored
@@ -743,7 +743,7 @@ func (m *Client) AddLogicalRouterPolicy(_ context.Context, routerName string, po
return fmt.Errorf("logical router %q not found", routerName)
}
if policy.UUID == "" {
policy.UUID = utils.GenerateResourceID("lrp")
policy.UUID = awsidentifiers.GenerateResourceID("lrp")
}
stored := *policy
m.LRPolicies[policy.UUID] = &stored
@@ -827,7 +827,7 @@ func (m *Client) CreatePortGroup(_ context.Context, name string, ports []string)
return fmt.Errorf("port group %q already exists", name)
}
pg := &nbdb.PortGroup{
UUID: utils.GenerateResourceID("pg"),
UUID: awsidentifiers.GenerateResourceID("pg"),
Name: name,
Ports: ports,
}
@@ -844,7 +844,7 @@ func (m *Client) EnsurePortGroup(_ context.Context, name string, ports []string)
return &result, false, nil
}
pg := &nbdb.PortGroup{
UUID: utils.GenerateResourceID("pg"),
UUID: awsidentifiers.GenerateResourceID("pg"),
Name: name,
Ports: ports,
}
@@ -951,7 +951,7 @@ func (m *Client) EnsureAddressSet(_ context.Context, name string, addresses []st
return existing.UUID, nil
}
as := &nbdb.AddressSet{
UUID: utils.GenerateResourceID("as"),
UUID: awsidentifiers.GenerateResourceID("as"),
Name: name,
Addresses: slices.Clone(addresses),
}
@@ -986,7 +986,7 @@ func (m *Client) AddACLs(_ context.Context, portGroupName string, specs []ovn.AC
}
for _, spec := range specs {
acl := &nbdb.ACL{
UUID: utils.GenerateResourceID("acl"),
UUID: awsidentifiers.GenerateResourceID("acl"),
Direction: spec.Direction,
Priority: spec.Priority,
Match: spec.Match,
@@ -1065,7 +1065,7 @@ func (m *Client) ReplaceACLs(_ context.Context, portGroupName string, specs []ov
pg.ACLs = pg.ACLs[:0]
for _, spec := range specs {
acl := &nbdb.ACL{
UUID: utils.GenerateResourceID("acl"),
UUID: awsidentifiers.GenerateResourceID("acl"),
Direction: spec.Direction,
Priority: spec.Priority,
Match: spec.Match,
@@ -1119,7 +1119,7 @@ func (m *Client) SetGatewayChassis(_ context.Context, lrpName string, chassisNam
return nil
}
gc := &nbdb.GatewayChassis{
UUID: utils.GenerateResourceID("gc"),
UUID: awsidentifiers.GenerateResourceID("gc"),
Name: gcName,
ChassisName: chassisName,
Priority: priority,
@@ -1181,7 +1181,7 @@ func (m *Client) SeedGatewayChassis(lrpName string, gc *nbdb.GatewayChassis) {
m.Mu.Lock()
defer m.Mu.Unlock()
if gc.UUID == "" {
gc.UUID = utils.GenerateResourceID("gc")
gc.UUID = awsidentifiers.GenerateResourceID("gc")
}
m.GatewayChassis[gc.UUID] = gc
if lrp, ok := m.RouterPorts[lrpName]; ok {
@@ -18,11 +18,11 @@ import (
awss3 "github.com/aws/aws-sdk-go/service/s3"
"github.com/mulgadc/bluebottle/pkg/safecast"
viperblocklegacyv1 "github.com/mulgadc/spinifex/contracts/viperblockd/legacy/v1"
awsidentifiers "github.com/mulgadc/spinifex/spinifex/foundation/aws/identifiers"
"github.com/mulgadc/spinifex/spinifex/providers/ebs"
"github.com/mulgadc/spinifex/spinifex/providers/objectstore"
"github.com/mulgadc/spinifex/spinifex/runtime/compute/nbd"
hostprocess "github.com/mulgadc/spinifex/spinifex/runtime/host/process"
"github.com/mulgadc/spinifex/spinifex/utils"
vbtypes "github.com/mulgadc/viperblock/types"
"github.com/mulgadc/viperblock/viperblock"
"github.com/nats-io/nats.go"
@@ -1047,7 +1047,7 @@ func handleCreateSnapshot(ctx context.Context, cfg *Config, nc *nats.Conn, msg *
return
}
operationID := utils.GenerateResourceID("op")
operationID := awsidentifiers.GenerateResourceID("op")
respondProvider(ctx, msg, ebsprovider.CreateSnapshotResponse{
Versioned: ebsprovider.NewVersioned(),
OperationID: operationID,
-13
View File
@@ -2,8 +2,6 @@ package utils
import (
"bytes"
"crypto/rand"
"encoding/hex"
"encoding/json"
"errors"
"log/slog"
@@ -13,17 +11,6 @@ import (
"github.com/mulgadc/spinifex/spinifex/foundation/aws/errors"
)
// GenerateResourceID generates a unique resource ID with the given prefix.
// Format: {prefix}-{17 hex chars} using crypto/rand.
func GenerateResourceID(prefix string) string {
b := make([]byte, 9)
if _, err := rand.Read(b); err != nil {
//nolint:forbidigo // Continuing after the CSPRNG fails could create predictable resource IDs.
panic("crypto/rand failed: " + err.Error())
}
return prefix + "-" + hex.EncodeToString(b)[:17]
}
// GenerateErrorPayload serializes an ec2.ResponseError with the given code as JSON.
func GenerateErrorPayload(code string) (jsonResponse []byte) {
return GenerateErrorPayloadWithMessage(code, "")
-28
View File
@@ -1,39 +1,11 @@
package utils
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGenerateResourceID(t *testing.T) {
tests := []struct {
prefix string
}{
{"i"},
{"r"},
{"vol"},
{"snap"},
{"key"},
{"eigw"},
{"ami"},
}
for _, tt := range tests {
t.Run(tt.prefix, func(t *testing.T) {
id := GenerateResourceID(tt.prefix)
assert.True(t, strings.HasPrefix(id, tt.prefix+"-"))
// prefix + "-" + 17 hex chars
assert.Len(t, id, len(tt.prefix)+1+17)
// Verify uniqueness
id2 := GenerateResourceID(tt.prefix)
assert.NotEqual(t, id, id2)
})
}
}
func TestUnmarshalJsonPayload(t *testing.T) {
type TestStruct struct {
Name string `json:"name"`