Skip to content

Commit

Permalink
Add fallback to fetch limits from EC2 API (#782)
Browse files Browse the repository at this point in the history
(cherry picked from commit 3b0f876)
  • Loading branch information
Claes Mogren authored and jaypipes committed Jan 31, 2020
1 parent 6b11dee commit ab96e4d
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 5 deletions.
20 changes: 18 additions & 2 deletions pkg/awsutils/awsutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -916,9 +916,25 @@ func (cache *EC2InstanceMetadataCache) GetENIipLimit() (int, error) {
// GetENILimit returns the number of ENIs can be attached to an instance
func (cache *EC2InstanceMetadataCache) GetENILimit() (int, error) {
eniLimit, ok := InstanceENIsAvailable[cache.instanceType]

if !ok {
return 0, errors.New(fmt.Sprintf("%s: %s", UnknownInstanceType, cache.instanceType))
// Fetch from EC2 API
describeInstanceTypesInput := &ec2.DescribeInstanceTypesInput{InstanceTypes: []*string{aws.String(cache.instanceType)}}
output, err := cache.ec2SVC.DescribeInstanceTypes(describeInstanceTypesInput)
if err != nil || len(output.InstanceTypes) != 1 {
log.Errorf("", err)
return 0, errors.New(fmt.Sprintf("Failed calling DescribeInstanceTypes for `%s`: %v", cache.instanceType, err))
}
info := output.InstanceTypes[0]
// Ignore any missing values
instanceType := aws.StringValue(info.InstanceType)
eniLimit = int(aws.Int64Value(info.NetworkInfo.MaximumNetworkInterfaces))
ipLimit := int(aws.Int64Value(info.NetworkInfo.Ipv4AddressesPerInterface))
if instanceType != "" && eniLimit > 0 && ipLimit > 0 {
InstanceENIsAvailable[instanceType] = eniLimit
InstanceIPsAvailable[instanceType] = ipLimit
} else {
return 0, errors.New(fmt.Sprintf("%s: %s", UnknownInstanceType, cache.instanceType))
}
}
return eniLimit, nil
}
Expand Down
21 changes: 21 additions & 0 deletions pkg/awsutils/awsutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,27 @@ func TestFreeENIDescribeErr(t *testing.T) {
assert.Error(t, err)
}

func TestDescribeInstanceTypes(t *testing.T) {
ctrl, _, mockEC2 := setup(t)
defer ctrl.Finish()
mockEC2.EXPECT().DescribeInstanceTypes(gomock.Any()).Return(&ec2.DescribeInstanceTypesOutput{
InstanceTypes: []*ec2.InstanceTypeInfo{
{InstanceType: aws.String("not-there"), NetworkInfo: &ec2.NetworkInfo{
MaximumNetworkInterfaces: aws.Int64(9),
Ipv4AddressesPerInterface: aws.Int64(99)},
},
},
NextToken: nil,
}, nil)

ins := &EC2InstanceMetadataCache{ec2SVC: mockEC2}
ins.instanceType = "not-there"
value, err := ins.GetENILimit()
assert.NoError(t, err)
assert.Equal(t, 9, value)
assert.Equal(t, 99, InstanceIPsAvailable[ins.instanceType])
}

func TestAllocIPAddress(t *testing.T) {
ctrl, _, mockEC2 := setup(t)
defer ctrl.Finish()
Expand Down
6 changes: 3 additions & 3 deletions pkg/awsutils/gen_vpc_ip_limits.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ func main() {
log.Fatal(err)
}
svc := ec2.New(sess)
describeInstanceTypeInput := &ec2.DescribeInstanceTypesInput{}
describeInstanceTypesInput := &ec2.DescribeInstanceTypesInput{}

eniLimitMap := make(map[string]ENILimit)
for {
output, err := svc.DescribeInstanceTypes(describeInstanceTypeInput)
output, err := svc.DescribeInstanceTypes(describeInstanceTypesInput)
if err != nil {
log.Fatal(err)
}
Expand All @@ -71,7 +71,7 @@ func main() {
if output.NextToken == nil {
break
}
describeInstanceTypeInput = &ec2.DescribeInstanceTypesInput{
describeInstanceTypesInput = &ec2.DescribeInstanceTypesInput{
NextToken: output.NextToken,
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/ec2wrapper/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
type EC2 interface {
CreateNetworkInterface(input *ec2svc.CreateNetworkInterfaceInput) (*ec2svc.CreateNetworkInterfaceOutput, error)
DescribeInstances(input *ec2svc.DescribeInstancesInput) (*ec2svc.DescribeInstancesOutput, error)
DescribeInstanceTypes(input *ec2svc.DescribeInstanceTypesInput) (*ec2svc.DescribeInstanceTypesOutput, error)
AttachNetworkInterface(input *ec2svc.AttachNetworkInterfaceInput) (*ec2svc.AttachNetworkInterfaceOutput, error)
DeleteNetworkInterface(input *ec2svc.DeleteNetworkInterfaceInput) (*ec2svc.DeleteNetworkInterfaceOutput, error)
DetachNetworkInterface(input *ec2svc.DetachNetworkInterfaceInput) (*ec2svc.DetachNetworkInterfaceOutput, error)
Expand Down
13 changes: 13 additions & 0 deletions pkg/ec2wrapper/mocks/ec2wrapper_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ab96e4d

Please sign in to comment.