fix: return SubnetArn and AWS's default subnet fields from CreateSubnet and DescribeSubnets

This commit is contained in:
Julian Sommer
2026-09-30 09:29:57 +10:00
parent a15084afd1
commit ba0e96082a
2 changed files with 60 additions and 0 deletions
+22
View File
@@ -13,6 +13,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/mulgadc/spinifex/spinifex/arn"
"github.com/mulgadc/spinifex/spinifex/awserrors"
"github.com/mulgadc/spinifex/spinifex/config"
"github.com/mulgadc/spinifex/spinifex/filterutil"
@@ -132,6 +133,15 @@ func (s *VPCServiceImpl) localAZ() string {
return s.config.AZ
}
// region returns the configured AWS region, falling back to the default when
// no config or region is wired.
func (s *VPCServiceImpl) region() string {
if s.config == nil || s.config.Region == "" {
return config.DefaultAWSRegion
}
return s.config.Region
}
// NewVPCServiceImplWithNATS creates a VPC service with NATS JetStream for persistence.
func NewVPCServiceImplWithNATS(ctx context.Context, cfg *config.Config, natsConn *nats.Conn) (*VPCServiceImpl, error) {
js, err := jetstream.New(natsConn)
@@ -1265,6 +1275,18 @@ func (s *VPCServiceImpl) subnetRecordToEC2(record *SubnetRecord, availableIPs in
AvailableIpAddressCount: aws.Int64(int64(availableIPs)),
OwnerId: aws.String(accountID),
MapPublicIpOnLaunch: aws.Bool(record.MapPublicIpOnLaunch),
SubnetArn: aws.String(arn.FormatEC2(arn.EC2Subnet, s.region(), accountID, record.SubnetId)),
// Spinifex subnets are IPv4-only with no customer-owned pool, and
// instances are named ip-<a-b-c-d> with no resource-name records.
AssignIpv6AddressOnCreation: aws.Bool(false),
EnableDns64: aws.Bool(false),
Ipv6Native: aws.Bool(false),
MapCustomerOwnedIpOnLaunch: aws.Bool(false),
PrivateDnsNameOptionsOnLaunch: &ec2.PrivateDnsNameOptionsOnLaunch{
HostnameType: aws.String(ec2.HostnameTypeIpName),
EnableResourceNameDnsARecord: aws.Bool(false),
EnableResourceNameDnsAAAARecord: aws.Bool(false),
},
}
subnet.Tags = utils.MapToEC2Tags(record.Tags)
@@ -287,6 +287,44 @@ func TestCreateSubnet(t *testing.T) {
assert.Equal(t, int64(251), *out.Subnet.AvailableIpAddressCount)
}
// TestSubnetResponse_AWSDefaultFields checks the ARN and the fields AWS
// reports for a new subnet, on both the create and describe paths.
func TestSubnetResponse_AWSDefaultFields(t *testing.T) {
t.Parallel()
svc := setupTestVPCService(t)
svc.config = &config.Config{Region: "ap-southeast-2"}
vpcID := createTestVPC(t, svc, "10.0.0.0/16")
out, err := svc.CreateSubnet(context.Background(), &ec2.CreateSubnetInput{
VpcId: aws.String(vpcID),
CidrBlock: aws.String("10.0.1.0/24"),
}, testAccountID)
require.NoError(t, err)
desc, err := svc.DescribeSubnets(context.Background(), &ec2.DescribeSubnetsInput{
SubnetIds: []*string{out.Subnet.SubnetId},
}, testAccountID)
require.NoError(t, err)
require.Len(t, desc.Subnets, 1)
for name, subnet := range map[string]*ec2.Subnet{"create": out.Subnet, "describe": desc.Subnets[0]} {
assert.Equal(t, "arn:aws:ec2:ap-southeast-2:"+testAccountID+":subnet/"+*out.Subnet.SubnetId, aws.StringValue(subnet.SubnetArn), name)
for field, v := range map[string]*bool{
"AssignIpv6AddressOnCreation": subnet.AssignIpv6AddressOnCreation,
"EnableDns64": subnet.EnableDns64,
"Ipv6Native": subnet.Ipv6Native,
"MapCustomerOwnedIpOnLaunch": subnet.MapCustomerOwnedIpOnLaunch,
} {
require.NotNil(t, v, "%s %s", name, field)
assert.False(t, *v, "%s %s", name, field)
}
assert.Equal(t, &ec2.PrivateDnsNameOptionsOnLaunch{
HostnameType: aws.String("ip-name"),
EnableResourceNameDnsARecord: aws.Bool(false),
EnableResourceNameDnsAAAARecord: aws.Bool(false),
}, subnet.PrivateDnsNameOptionsOnLaunch, name)
}
}
func TestCreateSubnet_MissingVpcId(t *testing.T) {
t.Parallel()
svc := setupTestVPCService(t)