in pkg/awsutils/awsutils.go [1114:1211]
func (cache *EC2InstanceMetadataCache) DescribeAllENIs() (DescribeAllENIsResult, error) {
// Fetch all local ENI info from metadata
allENIs, err := cache.GetAttachedENIs()
if err != nil {
return DescribeAllENIsResult{}, errors.Wrap(err, "DescribeAllENIs: failed to get local ENI metadata")
}
eniMap := make(map[string]ENIMetadata, len(allENIs))
var eniIDs []string
for _, eni := range allENIs {
eniIDs = append(eniIDs, eni.ENIID)
eniMap[eni.ENIID] = eni
}
var ec2Response *ec2.DescribeNetworkInterfacesOutput
// Try calling EC2 to describe the interfaces.
for retryCount := 0; retryCount < maxENIEC2APIRetries && len(eniIDs) > 0; retryCount++ {
input := &ec2.DescribeNetworkInterfacesInput{NetworkInterfaceIds: aws.StringSlice(eniIDs)}
start := time.Now()
ec2Response, err = cache.ec2SVC.DescribeNetworkInterfacesWithContext(context.Background(), input)
awsAPILatency.WithLabelValues("DescribeNetworkInterfaces", fmt.Sprint(err != nil), awsReqStatus(err)).Observe(msSince(start))
if err == nil {
// No error, exit the loop
break
}
awsAPIErrInc("DescribeNetworkInterfaces", err)
log.Errorf("Failed to call ec2:DescribeNetworkInterfaces for %v: %v", aws.StringValueSlice(input.NetworkInterfaceIds), err)
if aerr, ok := err.(awserr.Error); ok {
if aerr.Code() == "InvalidNetworkInterfaceID.NotFound" {
badENIID := badENIID(aerr.Message())
log.Debugf("Could not find interface: %s, ID: %s", aerr.Message(), badENIID)
awsAPIErrInc("IMDSMetaDataOutOfSync", err)
// Remove this ENI from the map
delete(eniMap, badENIID)
// Remove the failing ENI ID from the EC2 API request and try again
var tmpENIIDs []string
for _, eniID := range eniIDs {
if eniID != badENIID {
tmpENIIDs = append(tmpENIIDs, eniID)
}
}
eniIDs = tmpENIIDs
continue
}
}
// For other errors sleep a short while before the next retry
time.Sleep(time.Duration(retryCount*10) * time.Millisecond)
}
if err != nil {
return DescribeAllENIsResult{}, err
}
// Collect the verified ENIs
var verifiedENIs []ENIMetadata
for _, eniMetadata := range eniMap {
verifiedENIs = append(verifiedENIs, eniMetadata)
}
// Collect ENI response into ENI metadata and tags.
var trunkENI string
var multiCardENIIDs []string
efaENIs := make(map[string]bool, 0)
tagMap := make(map[string]TagMap, len(ec2Response.NetworkInterfaces))
for _, ec2res := range ec2Response.NetworkInterfaces {
log.Infof("Got network cardindex %v for ENI %v", aws.Int64Value(ec2res.Attachment.NetworkCardIndex), aws.StringValue(ec2res.NetworkInterfaceId))
if ec2res.Attachment != nil && aws.Int64Value(ec2res.Attachment.DeviceIndex) == 0 && !aws.BoolValue(ec2res.Attachment.DeleteOnTermination) {
log.Warn("Primary ENI will not get deleted when node terminates because 'delete_on_termination' is set to false")
}
eniID := aws.StringValue(ec2res.NetworkInterfaceId)
if aws.Int64Value(ec2res.Attachment.NetworkCardIndex) > 0 {
multiCardENIIDs = append(multiCardENIIDs, eniID)
}
eniMetadata := eniMap[eniID]
interfaceType := aws.StringValue(ec2res.InterfaceType)
log.Infof("%s is of type: %s", eniID, interfaceType)
// This assumes we only have one trunk attached to the node..
if interfaceType == "trunk" {
trunkENI = eniID
}
if interfaceType == "efa" {
efaENIs[eniID] = true
}
// Check IPv4 addresses
logOutOfSyncState(eniID, eniMetadata.IPv4Addresses, ec2res.PrivateIpAddresses)
tagMap[eniMetadata.ENIID] = convertSDKTagsToTags(ec2res.TagSet)
}
return DescribeAllENIsResult{
ENIMetadata: verifiedENIs,
TagMap: tagMap,
TrunkENI: trunkENI,
EFAENIs: efaENIs,
MultiCardENIIDs: multiCardENIIDs,
}, nil
}