From 91e4efb0eff2578e5725ee42a8bdcd870508e3eb Mon Sep 17 00:00:00 2001 From: Julian Sommer <115516918+juliansommer@users.noreply.github.com> Date: Wed, 1 Apr 2026 15:27:43 +1000 Subject: [PATCH] feat: extract tag helper --- spinifex/handlers/ec2/eigw/service_impl.go | 12 +--------- spinifex/handlers/ec2/eip/service_impl.go | 13 +--------- spinifex/handlers/ec2/igw/service_impl.go | 12 +--------- .../handlers/ec2/snapshot/service_impl.go | 12 +--------- spinifex/handlers/ec2/vpc/eni.go | 12 +--------- spinifex/handlers/ec2/vpc/security_group.go | 12 +--------- spinifex/handlers/ec2/vpc/service_impl.go | 24 ++----------------- spinifex/utils/tags.go | 22 +++++++++++++++++ 8 files changed, 30 insertions(+), 89 deletions(-) create mode 100644 spinifex/utils/tags.go diff --git a/spinifex/handlers/ec2/eigw/service_impl.go b/spinifex/handlers/ec2/eigw/service_impl.go index 96887e7c9..5393189bc 100644 --- a/spinifex/handlers/ec2/eigw/service_impl.go +++ b/spinifex/handlers/ec2/eigw/service_impl.go @@ -94,20 +94,10 @@ func (s *EgressOnlyIGWServiceImpl) CreateEgressOnlyInternetGateway(input *ec2.Cr EgressOnlyInternetGatewayId: eigwID, VpcId: *input.VpcId, State: "attached", - Tags: make(map[string]string), + Tags: utils.ExtractTags(input.TagSpecifications, "egress-only-internet-gateway"), CreatedAt: time.Now(), } - for _, tagSpec := range input.TagSpecifications { - if tagSpec.ResourceType != nil && *tagSpec.ResourceType == "egress-only-internet-gateway" { - for _, tag := range tagSpec.Tags { - if tag.Key != nil && tag.Value != nil { - record.Tags[*tag.Key] = *tag.Value - } - } - } - } - data, err := json.Marshal(record) if err != nil { return nil, fmt.Errorf("failed to marshal Egress-only IGW record: %w", err) diff --git a/spinifex/handlers/ec2/eip/service_impl.go b/spinifex/handlers/ec2/eip/service_impl.go index f83ac8555..3e086d34f 100644 --- a/spinifex/handlers/ec2/eip/service_impl.go +++ b/spinifex/handlers/ec2/eip/service_impl.go @@ -93,21 +93,10 @@ func (s *EIPServiceImpl) AllocateAddress(input *ec2.AllocateAddressInput, accoun PublicIp: publicIP, PoolName: poolName, State: "allocated", - Tags: make(map[string]string), + Tags: utils.ExtractTags(input.TagSpecifications, "elastic-ip"), CreatedAt: time.Now(), } - // Store tags from input. - for _, tagSpec := range input.TagSpecifications { - if tagSpec.ResourceType != nil && *tagSpec.ResourceType == "elastic-ip" { - for _, tag := range tagSpec.Tags { - if tag.Key != nil && tag.Value != nil { - record.Tags[*tag.Key] = *tag.Value - } - } - } - } - data, err := json.Marshal(record) if err != nil { return nil, fmt.Errorf("failed to marshal EIP record: %w", err) diff --git a/spinifex/handlers/ec2/igw/service_impl.go b/spinifex/handlers/ec2/igw/service_impl.go index 8cc50c715..94d416e80 100644 --- a/spinifex/handlers/ec2/igw/service_impl.go +++ b/spinifex/handlers/ec2/igw/service_impl.go @@ -91,20 +91,10 @@ func (s *IGWServiceImpl) createIGW(input *ec2.CreateInternetGatewayInput, accoun record := IGWRecord{ InternetGatewayId: igwID, State: "available", - Tags: make(map[string]string), + Tags: utils.ExtractTags(input.TagSpecifications, "internet-gateway"), CreatedAt: time.Now(), } - for _, tagSpec := range input.TagSpecifications { - if tagSpec.ResourceType != nil && *tagSpec.ResourceType == "internet-gateway" { - for _, tag := range tagSpec.Tags { - if tag.Key != nil && tag.Value != nil { - record.Tags[*tag.Key] = *tag.Value - } - } - } - } - data, err := json.Marshal(record) if err != nil { return nil, fmt.Errorf("failed to marshal IGW record: %w", err) diff --git a/spinifex/handlers/ec2/snapshot/service_impl.go b/spinifex/handlers/ec2/snapshot/service_impl.go index af4ff6012..24c8b3821 100644 --- a/spinifex/handlers/ec2/snapshot/service_impl.go +++ b/spinifex/handlers/ec2/snapshot/service_impl.go @@ -268,23 +268,13 @@ func (s *SnapshotServiceImpl) CreateSnapshot(input *ec2.CreateSnapshotInput, acc Encrypted: volumeConfig.VolumeMetadata.IsEncrypted, OwnerID: accountID, AvailabilityZone: volumeConfig.VolumeMetadata.AvailabilityZone, - Tags: make(map[string]string), + Tags: utils.ExtractTags(input.TagSpecifications, "snapshot"), } if input.Description != nil { snapshotCfg.Description = *input.Description } - for _, tagSpec := range input.TagSpecifications { - if tagSpec.ResourceType != nil && *tagSpec.ResourceType == "snapshot" { - for _, tag := range tagSpec.Tags { - if tag.Key != nil && tag.Value != nil { - snapshotCfg.Tags[*tag.Key] = *tag.Value - } - } - } - } - // Track the volume→snapshot dependency in KV before persisting to S3. // This ensures we never have an untracked snapshot in S3. if err := s.addSnapshotRef(volumeID, snapshotID); err != nil { diff --git a/spinifex/handlers/ec2/vpc/eni.go b/spinifex/handlers/ec2/vpc/eni.go index fed1cc05c..768621807 100644 --- a/spinifex/handlers/ec2/vpc/eni.go +++ b/spinifex/handlers/ec2/vpc/eni.go @@ -100,20 +100,10 @@ func (s *VPCServiceImpl) CreateNetworkInterface(input *ec2.CreateNetworkInterfac Description: description, Status: "available", SecurityGroupIds: sgIds, - Tags: make(map[string]string), + Tags: utils.ExtractTags(input.TagSpecifications, "network-interface"), CreatedAt: time.Now(), } - for _, tagSpec := range input.TagSpecifications { - if tagSpec.ResourceType != nil && *tagSpec.ResourceType == "network-interface" { - for _, tag := range tagSpec.Tags { - if tag.Key != nil && tag.Value != nil { - record.Tags[*tag.Key] = *tag.Value - } - } - } - } - data, err := json.Marshal(record) if err != nil { return nil, fmt.Errorf("failed to marshal ENI record: %w", err) diff --git a/spinifex/handlers/ec2/vpc/security_group.go b/spinifex/handlers/ec2/vpc/security_group.go index b6382c608..cda21a04e 100644 --- a/spinifex/handlers/ec2/vpc/security_group.go +++ b/spinifex/handlers/ec2/vpc/security_group.go @@ -112,20 +112,10 @@ func (s *VPCServiceImpl) CreateSecurityGroup(input *ec2.CreateSecurityGroupInput VpcId: vpcId, IngressRules: []SGRule{}, EgressRules: defaultEgress, - Tags: make(map[string]string), + Tags: utils.ExtractTags(input.TagSpecifications, "security-group"), CreatedAt: time.Now(), } - for _, tagSpec := range input.TagSpecifications { - if tagSpec.ResourceType != nil && *tagSpec.ResourceType == "security-group" { - for _, tag := range tagSpec.Tags { - if tag.Key != nil && tag.Value != nil { - record.Tags[*tag.Key] = *tag.Value - } - } - } - } - data, err := json.Marshal(record) if err != nil { return nil, fmt.Errorf("failed to marshal security group record: %w", err) diff --git a/spinifex/handlers/ec2/vpc/service_impl.go b/spinifex/handlers/ec2/vpc/service_impl.go index 80095bcf7..b6671f0f1 100644 --- a/spinifex/handlers/ec2/vpc/service_impl.go +++ b/spinifex/handlers/ec2/vpc/service_impl.go @@ -220,20 +220,10 @@ func (s *VPCServiceImpl) CreateVpc(input *ec2.CreateVpcInput, accountID string) VNI: vni, EnableDnsSupport: true, // AWS default EnableDnsHostnames: false, // AWS default - Tags: make(map[string]string), + Tags: utils.ExtractTags(input.TagSpecifications, "vpc"), CreatedAt: time.Now(), } - for _, tagSpec := range input.TagSpecifications { - if tagSpec.ResourceType != nil && *tagSpec.ResourceType == "vpc" { - for _, tag := range tagSpec.Tags { - if tag.Key != nil && tag.Value != nil { - record.Tags[*tag.Key] = *tag.Value - } - } - } - } - data, err := json.Marshal(record) if err != nil { return nil, fmt.Errorf("failed to marshal VPC record: %w", err) @@ -494,20 +484,10 @@ func (s *VPCServiceImpl) CreateSubnet(input *ec2.CreateSubnetInput, accountID st AvailabilityZone: az, State: "available", IsDefault: false, - Tags: make(map[string]string), + Tags: utils.ExtractTags(input.TagSpecifications, "subnet"), CreatedAt: time.Now(), } - for _, tagSpec := range input.TagSpecifications { - if tagSpec.ResourceType != nil && *tagSpec.ResourceType == "subnet" { - for _, tag := range tagSpec.Tags { - if tag.Key != nil && tag.Value != nil { - record.Tags[*tag.Key] = *tag.Value - } - } - } - } - data, err := json.Marshal(record) if err != nil { return nil, fmt.Errorf("failed to marshal subnet record: %w", err) diff --git a/spinifex/utils/tags.go b/spinifex/utils/tags.go new file mode 100644 index 000000000..c78b7bb1d --- /dev/null +++ b/spinifex/utils/tags.go @@ -0,0 +1,22 @@ +package utils + +import ( + "github.com/aws/aws-sdk-go/service/ec2" +) + +// ExtractTags returns a map of tags from the TagSpecification that matches +// the given resourceType. If no specification matches, the returned map is +// empty (never nil). +func ExtractTags(tagSpecs []*ec2.TagSpecification, resourceType string) map[string]string { + tags := make(map[string]string) + for _, tagSpec := range tagSpecs { + if tagSpec.ResourceType != nil && *tagSpec.ResourceType == resourceType { + for _, tag := range tagSpec.Tags { + if tag.Key != nil && tag.Value != nil { + tags[*tag.Key] = *tag.Value + } + } + } + } + return tags +}