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{
|
for _, arns := range p.chunkIDs(containerInstancesArns) {
|
||||||
ContainerInstances: containerInstancesArns,
|
resp, err := client.ecs.DescribeContainerInstancesWithContext(ctx, &ecs.DescribeContainerInstancesInput{
|
||||||
Cluster: clusterName,
|
ContainerInstances: arns,
|
||||||
})
|
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
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Unable to describe instances: %s", err)
|
log.Errorf("Unable to describe container instances: %v", err)
|
||||||
return nil, 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
|
return ec2Instances, nil
|
||||||
|
@ -414,3 +418,19 @@ func (p *Provider) loadECSConfig(ctx context.Context, client *awsClient) (*types
|
||||||
|
|
||||||
return p.buildConfiguration(instances)
|
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