Skip to content

Commit 4ba9096

Browse files
committed
fix: pass nil tags when task definition has no tags
AWS rejects RegisterTaskDefinition with an empty Tags slice ("Tags can not be empty"). #43 passed describeResult.Tags directly, which is an empty slice for untagged task definitions rather than nil. The SDK treats nil (omit the field) and []Tag{} (empty list) differently. Add nilIfEmpty() helper that converts an empty slice to nil so untagged task definitions continue to work, while tagged task definitions still propagate their tags correctly.
1 parent 5a34447 commit 4ba9096

5 files changed

Lines changed: 32 additions & 7 deletions

File tree

lib/deploy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func deployService(ctx log.Interface, cluster, imageTag string, imageTags []stri
108108
RequiresCompatibilities: taskDefinition.Compatibilities,
109109
TaskRoleArn: taskDefinition.TaskRoleArn,
110110
Volumes: taskDefinition.Volumes,
111-
Tags: describeTaskResult.Tags,
111+
Tags: nilIfEmpty(describeTaskResult.Tags),
112112
})
113113
if err != nil {
114114
ctx.WithError(err).Error("Can't register task definition")

lib/run.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ import (
1111
// RunTask runs the specified one-off task in the cluster using the task definition
1212
func RunTask(profile, cluster, service, taskDefinitionName, imageTag string, imageTags []string, workDir, containerName, awslogGroup, launchType string, args []string) (exitCode int, err error) {
1313
ctx := log.WithFields(log.Fields{
14-
"task_definition": taskDefinitionName,
15-
"launch_type": launchType,
16-
})
14+
"task_definition": taskDefinitionName,
15+
"launch_type": launchType,
16+
})
1717
err = makeSession(profile)
1818
if err != nil {
1919
return 1, err
2020
}
21-
21+
2222
svc := ecs.New(localSession)
2323

2424
describeResult, err := svc.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{
@@ -68,7 +68,7 @@ func RunTask(profile, cluster, service, taskDefinitionName, imageTag string, ima
6868
RequiresCompatibilities: taskDefinition.Compatibilities,
6969
TaskRoleArn: taskDefinition.TaskRoleArn,
7070
Volumes: taskDefinition.Volumes,
71-
Tags: describeResult.Tags,
71+
Tags: nilIfEmpty(describeResult.Tags),
7272
})
7373
if err != nil {
7474
ctx.WithError(err).Error("Can't register task definition")

lib/runFargate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func RunFargate(profile, cluster, service, taskDefinitionName, imageTag string,
112112
RequiresCompatibilities: taskDefinition.Compatibilities,
113113
TaskRoleArn: taskDefinition.TaskRoleArn,
114114
Volumes: taskDefinition.Volumes,
115-
Tags: describeResult.Tags,
115+
Tags: nilIfEmpty(describeResult.Tags),
116116
})
117117
if err != nil {
118118
ctx.WithError(err).Error("Can't register task definition")

lib/util.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,13 @@ func fetchSecurityGroupsByName(svc *ec2.EC2, securityGroupFilter string) ([]*str
179179
// Return the filtered list of security group IDs
180180
return securityGroups, nil
181181
}
182+
183+
// nilIfEmpty returns nil when tags is empty so AWS doesn't reject the call with
184+
// "Tags can not be empty" — the AWS API rejects an empty Tags list at the wire level;
185+
// passing nil omits the field entirely.
186+
func nilIfEmpty(tags []*ecs.Tag) []*ecs.Tag {
187+
if len(tags) == 0 {
188+
return nil
189+
}
190+
return tags
191+
}

lib/util_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,28 @@ import (
44
"testing"
55

66
"github.com/aws/aws-sdk-go/aws"
7+
"github.com/aws/aws-sdk-go/service/ecs"
78
)
89

910
var testdata = map[string]string{
1011
"arn:aws:ecs:us-west-1:433844053624:task/scratchpower-staging/334083dd41c04b429cbf99ea7aeeef19": "334083dd41c04b429cbf99ea7aeeef19", // new longer
1112
"arn:aws:ecs:ap-southeast-2:208168611618:task/0c5027c6-7bbd-476b-a534-adaf56760ca9": "0c5027c6-7bbd-476b-a534-adaf56760ca9", // old format
1213
}
1314

15+
func TestNilIfEmpty(t *testing.T) {
16+
if nilIfEmpty(nil) != nil {
17+
t.Fatal("nil input should return nil")
18+
}
19+
if nilIfEmpty([]*ecs.Tag{}) != nil {
20+
t.Fatal("empty slice should return nil")
21+
}
22+
tags := []*ecs.Tag{{Key: aws.String("env"), Value: aws.String("prod")}}
23+
result := nilIfEmpty(tags)
24+
if len(result) != 1 || aws.StringValue(result[0].Key) != "env" || aws.StringValue(result[0].Value) != "prod" {
25+
t.Fatalf("non-empty slice should be returned unchanged, got %v", result)
26+
}
27+
}
28+
1429
func TestParseTaskUUID(t *testing.T) {
1530
for testArn, uuid := range testdata {
1631
if parsedUUID, err := parseTaskUUID(aws.String(testArn)); err != nil {

0 commit comments

Comments
 (0)