func()

in cns/restserver/ipam.go [888:987]


func (service *HTTPRestService) AssignDesiredIPConfigs(podInfo cns.PodInfo, desiredIPAddresses []string) ([]cns.PodIpInfo, error) {
	service.Lock()
	defer service.Unlock()

	// Gets the number of NCs which will determine the number of IPs given to a pod
	numOfNCs := len(service.state.ContainerStatus)
	// checks to make sure we have NCs before trying to get IPs
	if numOfNCs == 0 {
		return nil, ErrNoNCs
	}
	// Sets the number of desired IPs equal to the number of desired IPs passed in
	numDesiredIPAddresses := len(desiredIPAddresses)
	// Creates a slice of PodIpInfo with the size as number of NCs to hold the result for assigned IP configs
	podIPInfo := make([]cns.PodIpInfo, numDesiredIPAddresses)
	// creating a map for the loop to check to see if the IP in the pool is one of the desired IPs
	desiredIPMap := make(map[string]struct{})
	// slice to keep track of IP configs to assign
	ipConfigsToAssign := make([]cns.IPConfigurationStatus, 0)

	for _, desiredIP := range desiredIPAddresses {
		desiredIPMap[desiredIP] = struct{}{}
	}

	numIPConfigsAssigned := 0
	for _, ipConfig := range service.PodIPConfigState { //nolint:gocritic // ignore copy
		_, found := desiredIPMap[ipConfig.IPAddress]
		// keep searching until the all the desired IPs are found
		if !found {
			continue
		}

		switch ipConfig.GetState() { //nolint:exhaustive // ignoring PendingRelease case intentionally
		case types.Assigned:
			// This IP has already been assigned, if it is assigned to same pod add the IP to podIPInfo
			if ipConfig.PodInfo.Key() == podInfo.Key() {
				logger.Printf("[AssignDesiredIPConfigs]: IP Config [%+v] is already assigned to this Pod [%+v]", ipConfig, podInfo)
				if err := service.populateIPConfigInfoUntransacted(ipConfig, &podIPInfo[numIPConfigsAssigned]); err != nil {
					//nolint:goerr113 // return error
					return []cns.PodIpInfo{}, fmt.Errorf("[AssignDesiredIPConfigs] Failed to assign IP %+v requested for pod %+v since the IP is already assigned to %+v", ipConfig, podInfo, ipConfig.PodInfo)
				}
				numIPConfigsAssigned++
			} else {
				//nolint:goerr113 // return error
				return []cns.PodIpInfo{}, fmt.Errorf("[AssignDesiredIPConfigs] Desired IP is already assigned %+v, requested for pod %+v", ipConfig, podInfo)
			}
		case types.Available, types.PendingProgramming:
			// This race can happen during restart, where CNS state is lost and thus we have lost the NC programmed version
			// As part of reconcile, we mark IPs as Assigned which are already assigned to Pods (listed from APIServer)
			ipConfigsToAssign = append(ipConfigsToAssign, ipConfig)
		default:
			logger.Errorf("[AssignDesiredIPConfigs] Desired IP is not available %+v", ipConfig)
			//nolint:goerr113 // return error
			return podIPInfo, fmt.Errorf("IP not available")
		}

		// checks if found all of the desired IPs either as an available IP or already assigned to the pod
		if len(ipConfigsToAssign)+numIPConfigsAssigned == numDesiredIPAddresses {
			break
		}
	}

	// if we did not find all of the desired IPs return an error
	if len(ipConfigsToAssign)+numIPConfigsAssigned != numDesiredIPAddresses {
		//nolint:goerr113 // return error
		return podIPInfo, fmt.Errorf("not enough desired IPs found in pool")
	}

	failedToAssignIP := false
	// assigns all IPs that were found as available to the pod
	for i := range ipConfigsToAssign {
		if err := service.assignIPConfig(ipConfigsToAssign[i], podInfo); err != nil {
			logger.Errorf(err.Error())
			failedToAssignIP = true
			break
		}
		if err := service.populateIPConfigInfoUntransacted(ipConfigsToAssign[i], &podIPInfo[numIPConfigsAssigned]); err != nil {
			logger.Errorf(err.Error())
			failedToAssignIP = true
			break
		}
		// adds to the newly assigned IP to the counter
		numIPConfigsAssigned++
	}

	// if we were able to get at least one IP but not all of the desired IPs
	if failedToAssignIP {
		logger.Printf("[AssignDesiredIPConfigs] Failed to retrieve all desired IPs. Releasing all IPs that were found")
		for i := range ipConfigsToAssign {
			_, err := service.unassignIPConfig(ipConfigsToAssign[i], podInfo)
			if err != nil {
				logger.Errorf("[AssignDesiredIPConfigs] failed to mark IPConfig [%+v] back to Available. err: %v", ipConfigsToAssign[i], err)
			}
		}
		//nolint:goerr113 // return error
		return podIPInfo, fmt.Errorf("not all requested ips %v were found/available in the pool", desiredIPAddresses)
	}

	logger.Printf("[AssignDesiredIPConfigs] Successfully assigned all desired IPs for pod %+v", podInfo)
	return podIPInfo, nil
}