func()

in pkg/aws/ec2/api/helper.go [442:504]


func (h *ec2APIHelper) AssignIPv4AddressesAndWaitTillReady(eniID string, count int) ([]string, error) {
	var assignedIPs []string

	input := &ec2.AssignPrivateIpAddressesInput{
		NetworkInterfaceId:             &eniID,
		SecondaryPrivateIpAddressCount: aws.Int64(int64(count)),
	}

	assignPrivateIPOutput, err := h.ec2Wrapper.AssignPrivateIPAddresses(input)
	if err != nil {
		return assignedIPs, err
	}

	if assignPrivateIPOutput != nil && assignPrivateIPOutput.AssignedPrivateIpAddresses != nil &&
		len(assignPrivateIPOutput.AssignedPrivateIpAddresses) == 0 {
		return assignedIPs, fmt.Errorf("failed ot create %v ip address to eni %s", count, eniID)
	}

	ErrIPNotAttachedYet := fmt.Errorf("private IPv4 address is not attached yet")

	err = retry.OnError(waitForIPAttachment,
		func(err error) bool {
			if err == ErrIPNotAttachedYet {
				// Retry in case IPs are not attached yet
				return true
			}
			return false
		}, func() error {
			// Describe the network interface on which the new IPs are assigned
			interfaces, err := h.DescribeNetworkInterfaces([]*string{&eniID})
			// Re initialize the slice so we don't add IPs multiple time
			assignedIPs = []string{}
			if err == nil && len(interfaces) == 1 && interfaces[0].PrivateIpAddresses != nil {
				// Get the map of IPs returned by the describe network interface call
				ipAddress := map[string]bool{}
				for _, ipAddr := range interfaces[0].PrivateIpAddresses {
					ipAddress[*ipAddr.PrivateIpAddress] = true
				}
				// Verify the describe network interface returns all the IPs that were assigned in the
				// AssignPrivateIPAddresses call
				for _, ip := range assignPrivateIPOutput.AssignedPrivateIpAddresses {
					if _, ok := ipAddress[*ip.PrivateIpAddress]; !ok {
						// Even if one IP is not assigned, set the error so that we only return only the IPs that
						// are successfully assigned on the ENI
						err = ErrIPNotAttachedYet
					} else {
						assignedIPs = append(assignedIPs, *ip.PrivateIpAddress)
					}
				}
				//
				return err
			}
			return err
		})

	if err != nil {
		// If some of the assigned IP addresses were not yet returned in the describe network interface call,
		// returns the list of IPs that were returned
		return assignedIPs, err
	}

	return assignedIPs, nil
}