func()

in pkg/ipamd/ipamd.go [937:998]


func (c *IPAMContext) tryAssignIPs() (increasedPool bool, err error) {

	// If WARM_IP_TARGET is set, only proceed if we are short of target
	short, _, warmIPTargetsDefined := c.datastoreTargetState(nil)
	if warmIPTargetsDefined && short == 0 {
		return false, nil
	}

	// If WARM_IP_TARGET is set we only want to allocate up to that target to avoid overallocating and releasing
	toAllocate := c.maxIPsPerENI
	if warmIPTargetsDefined {
		toAllocate = short
	}

	// Find an ENI where we can add more IPs
	enis := c.dataStore.GetAllocatableENIs(c.maxIPsPerENI, c.useCustomNetworking)
	for _, eni := range enis {
		if len(eni.AvailableIPv4Cidrs) < c.maxIPsPerENI {
			currentNumberOfAllocatedIPs := len(eni.AvailableIPv4Cidrs)
			// Try to allocate all available IPs for this ENI
			resourcesToAllocate := min((c.maxIPsPerENI - currentNumberOfAllocatedIPs), toAllocate)
			output, err := c.awsClient.AllocIPAddresses(eni.ID, resourcesToAllocate)
			if err != nil && !containsPrivateIPAddressLimitExceededError(err) {
				log.Warnf("failed to allocate all available IP addresses on ENI %s, err: %v", eni.ID, err)
				// Try to just get one more IP
				output, err = c.awsClient.AllocIPAddresses(eni.ID, 1)
				if err != nil && !containsPrivateIPAddressLimitExceededError(err) {
					ipamdErrInc("increaseIPPoolAllocIPAddressesFailed")
					if c.useSubnetDiscovery && containsInsufficientCIDRsOrSubnetIPs(err) {
						continue
					}
					return false, errors.Wrap(err, fmt.Sprintf("failed to allocate one IP addresses on ENI %s, err ", eni.ID))
				}
			}

			var ec2ip4s []ec2types.NetworkInterfacePrivateIpAddress
			if containsPrivateIPAddressLimitExceededError(err) {
				log.Debug("AssignPrivateIpAddresses returned PrivateIpAddressLimitExceeded. This can happen if the data store is out of sync." +
					"Returning without an error here since we will verify the actual state by calling EC2 to see what addresses have already assigned to this ENI.")
				// This call to EC2 is needed to verify which IPs got attached to this ENI.
				ec2ip4s, err = c.awsClient.GetIPv4sFromEC2(eni.ID)
				if err != nil {
					ipamdErrInc("increaseIPPoolGetENIaddressesFailed")
					return true, errors.Wrap(err, "failed to get ENI IP addresses during IP allocation")
				}
			} else {
				if output == nil {
					ipamdErrInc("increaseIPPoolGetENIaddressesFailed")
					return true, errors.Wrap(err, "failed to get ENI IP addresses during IP allocation")
				}

				ec2Addrs := output.AssignedPrivateIpAddresses
				for _, ec2Addr := range ec2Addrs {
					ec2ip4s = append(ec2ip4s, ec2types.NetworkInterfacePrivateIpAddress{PrivateIpAddress: ec2Addr.PrivateIpAddress})
				}
			}
			c.addENIsecondaryIPsToDataStore(ec2ip4s, eni.ID)
			return true, nil
		}
	}
	return false, nil
}