Fix 400 bad request on AWS ECS API
This commit is contained in:
parent
a953d3ad89
commit
ff2e2d5026
2 changed files with 140 additions and 32 deletions
|
@ -347,43 +347,47 @@ func (p *Provider) lookupEc2Instances(ctx context.Context, client *awsClient, cl
|
|||
}
|
||||
}
|
||||
|
||||
resp, err := client.ecs.DescribeContainerInstancesWithContext(ctx, &ecs.DescribeContainerInstancesInput{
|
||||
ContainerInstances: containerInstancesArns,
|
||||
Cluster: clusterName,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Unable to describe container instances: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, container := range resp.ContainerInstances {
|
||||
instanceIds[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn)
|
||||
instanceArns = append(instanceArns, container.Ec2InstanceId)
|
||||
}
|
||||
|
||||
if len(instanceArns) > 0 {
|
||||
input := &ec2.DescribeInstancesInput{
|
||||
InstanceIds: instanceArns,
|
||||
}
|
||||
|
||||
err = client.ec2.DescribeInstancesPagesWithContext(ctx, input, func(page *ec2.DescribeInstancesOutput, lastPage bool) bool {
|
||||
if len(page.Reservations) > 0 {
|
||||
for _, r := range page.Reservations {
|
||||
for _, i := range r.Instances {
|
||||
if i.InstanceId != nil {
|
||||
ec2Instances[instanceIds[aws.StringValue(i.InstanceId)]] = i
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return !lastPage
|
||||
for _, arns := range p.chunkIDs(containerInstancesArns) {
|
||||
resp, err := client.ecs.DescribeContainerInstancesWithContext(ctx, &ecs.DescribeContainerInstancesInput{
|
||||
ContainerInstances: arns,
|
||||
Cluster: clusterName,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Unable to describe instances: %s", err)
|
||||
log.Errorf("Unable to describe container instances: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, container := range resp.ContainerInstances {
|
||||
instanceIds[aws.StringValue(container.Ec2InstanceId)] = aws.StringValue(container.ContainerInstanceArn)
|
||||
instanceArns = append(instanceArns, container.Ec2InstanceId)
|
||||
}
|
||||
}
|
||||
|
||||
if len(instanceArns) > 0 {
|
||||
for _, ids := range p.chunkIDs(instanceArns) {
|
||||
input := &ec2.DescribeInstancesInput{
|
||||
InstanceIds: ids,
|
||||
}
|
||||
|
||||
err := client.ec2.DescribeInstancesPagesWithContext(ctx, input, func(page *ec2.DescribeInstancesOutput, lastPage bool) bool {
|
||||
if len(page.Reservations) > 0 {
|
||||
for _, r := range page.Reservations {
|
||||
for _, i := range r.Instances {
|
||||
if i.InstanceId != nil {
|
||||
ec2Instances[instanceIds[aws.StringValue(i.InstanceId)]] = i
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return !lastPage
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Unable to describe instances [%s]: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ec2Instances, nil
|
||||
|
@ -414,3 +418,19 @@ func (p *Provider) loadECSConfig(ctx context.Context, client *awsClient) (*types
|
|||
|
||||
return p.buildConfiguration(instances)
|
||||
}
|
||||
|
||||
// chunkIDs ECS expects no more than 100 parameters be passed to a API call;
|
||||
// thus, pack each string into an array capped at 100 elements
|
||||
func (p *Provider) chunkIDs(ids []*string) [][]*string {
|
||||
var chuncked [][]*string
|
||||
for i := 0; i < len(ids); i += 100 {
|
||||
sliceEnd := -1
|
||||
if i+100 < len(ids) {
|
||||
sliceEnd = i + 100
|
||||
} else {
|
||||
sliceEnd = len(ids)
|
||||
}
|
||||
chuncked = append(chuncked, ids[i:sliceEnd])
|
||||
}
|
||||
return chuncked
|
||||
}
|
||||
|
|
88
provider/ecs/ecs_test.go
Normal file
88
provider/ecs/ecs_test.go
Normal file
|
@ -0,0 +1,88 @@
|
|||
package ecs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestChunkIDs(t *testing.T) {
|
||||
provider := &Provider{}
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
count int
|
||||
expected []int
|
||||
}{
|
||||
{
|
||||
desc: "0 element",
|
||||
count: 0,
|
||||
expected: []int(nil),
|
||||
},
|
||||
{
|
||||
desc: "1 element",
|
||||
count: 1,
|
||||
expected: []int{1},
|
||||
},
|
||||
{
|
||||
desc: "99 elements, 1 chunk",
|
||||
count: 99,
|
||||
expected: []int{99},
|
||||
},
|
||||
{
|
||||
desc: "100 elements, 1 chunk",
|
||||
count: 100,
|
||||
expected: []int{100},
|
||||
},
|
||||
{
|
||||
desc: "101 elements, 2 chunks",
|
||||
count: 101,
|
||||
expected: []int{100, 1},
|
||||
},
|
||||
{
|
||||
desc: "199 elements, 2 chunks",
|
||||
count: 199,
|
||||
expected: []int{100, 99},
|
||||
},
|
||||
{
|
||||
desc: "200 elements, 2 chunks",
|
||||
count: 200,
|
||||
expected: []int{100, 100},
|
||||
},
|
||||
{
|
||||
desc: "201 elements, 3 chunks",
|
||||
count: 201,
|
||||
expected: []int{100, 100, 1},
|
||||
},
|
||||
{
|
||||
desc: "555 elements, 5 chunks",
|
||||
count: 555,
|
||||
expected: []int{100, 100, 100, 100, 100, 55},
|
||||
},
|
||||
{
|
||||
desc: "1001 elements, 11 chunks",
|
||||
count: 1001,
|
||||
expected: []int{100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 1},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var IDs []*string
|
||||
for v := 0; v < test.count; v++ {
|
||||
IDs = append(IDs, aws.String("a"))
|
||||
}
|
||||
|
||||
var outCount []int
|
||||
for _, el := range provider.chunkIDs(IDs) {
|
||||
outCount = append(outCount, len(el))
|
||||
}
|
||||
|
||||
assert.Equal(t, test.expected, outCount)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue