in pkg/provider/branch/trunk/trunk.go [384:480]
func (t *trunkENI) CreateAndAssociateBranchENIs(pod *v1.Pod, securityGroups []string, eniCount int) ([]*ENIDetails, error) {
log := t.log.WithValues("request", "create", "pod namespace", pod.Namespace, "pod name", pod.Name)
branchENI, isPresent := t.getBranchFromCache(string(pod.UID))
if isPresent {
// Possible when older pod with same namespace and name is still being deleted
return nil, fmt.Errorf("cannot create new eni entry already exist, older entry : %v", branchENI)
}
if !t.canCreateMore() {
return nil, ErrCurrentlyAtMaxCapacity
}
// If the security group is empty use the instance security group
if securityGroups == nil || len(securityGroups) == 0 {
securityGroups = t.instance.CurrentInstanceSecurityGroups()
}
var newENIs []*ENIDetails
var err error
var nwInterface *ec2types.NetworkInterface
var vlanID int
for i := 0; i < eniCount; i++ {
// Assign VLAN
vlanID, err = t.assignVlanId()
if err != nil {
err = fmt.Errorf("assigning vlad id, %w", err)
trunkENIOperationsErrCount.WithLabelValues("assign_vlan_id").Inc()
break
}
// Vlan ID tag workaround, as describe trunk association is not supported with assumed role
tags := []ec2types.Tag{
{
Key: aws.String(config.VLandIDTag),
Value: aws.String(strconv.Itoa(vlanID)),
},
{
Key: aws.String(config.TrunkENIIDTag),
Value: &t.trunkENIId,
},
}
// append the nodeName tag to add to branch ENIs
tags = append(tags, t.nodeIDTag...)
// Create Branch ENI
nwInterface, err = t.ec2ApiHelper.CreateNetworkInterface(&BranchEniDescription,
aws.String(t.instance.SubnetID()), securityGroups, tags, nil, nil)
if err != nil {
err = fmt.Errorf("creating network interface, %w", err)
t.freeVlanId(vlanID)
branchENIOperationsFailureCount.WithLabelValues("creating_branch_eni_failed").Inc()
break
} else {
branchENIOperationsSuccessCount.WithLabelValues("created_branch_eni_succeeded").Inc()
}
// Branch ENI can have an IPv4 address, IPv6 address, or both
var v4Addr, v6Addr string
if nwInterface.PrivateIpAddress != nil {
v4Addr = *nwInterface.PrivateIpAddress
}
if nwInterface.Ipv6Address != nil {
v6Addr = *nwInterface.Ipv6Address
}
newENI := &ENIDetails{
ID: *nwInterface.NetworkInterfaceId, MACAdd: *nwInterface.MacAddress,
IPV4Addr: v4Addr, IPV6Addr: v6Addr, SubnetCIDR: t.instance.SubnetCidrBlock(),
SubnetV6CIDR: t.instance.SubnetV6CidrBlock(), VlanID: vlanID,
}
newENIs = append(newENIs, newENI)
// Associate Branch to trunk
var associationOutput *awsEc2.AssociateTrunkInterfaceOutput
associationOutput, err = t.ec2ApiHelper.AssociateBranchToTrunk(&t.trunkENIId, nwInterface.NetworkInterfaceId, vlanID)
if err != nil {
err = fmt.Errorf("associating branch to trunk, %w", err)
trunkENIOperationsErrCount.WithLabelValues("associate_branch").Inc()
break
}
newENI.AssociationID = *associationOutput.InterfaceAssociation.AssociationId
}
if err != nil {
log.Error(err, "failed to create ENI, moving the ENI to delete list")
// Moving to delete list, because it has all the retrying logic in case of failure
t.PushENIsToFrontOfDeleteQueue(nil, newENIs)
return nil, err
}
t.addBranchToCache(string(pod.UID), newENIs)
log.Info("successfully created branch interfaces", "interfaces", newENIs,
"security group used", securityGroups)
return newENIs, nil
}