func()

in pkg/controllers/provisioning/binpacking/packer.go [85:140]


func (p *Packer) Pack(ctx context.Context, constraints *v1alpha5.Constraints, pods []*v1.Pod, instanceTypes []cloudprovider.InstanceType) ([]*Packing, error) {
	defer metrics.Measure(packDuration.WithLabelValues(injection.GetNamespacedName(ctx).Name))()
	// Get daemons for overhead calculations
	daemons, err := p.getDaemons(ctx, constraints)
	if err != nil {
		return nil, fmt.Errorf("getting schedulable daemon pods, %w", err)
	}
	// Sort pods in decreasing order by the amount of CPU requested, if
	// CPU requested is equal compare memory requested.
	sort.Slice(pods, func(a, b int) bool {
		resourcePodA := resources.RequestsForPods(pods[a])
		resourcePodB := resources.RequestsForPods(pods[b])
		if resourcePodA.Cpu().Equal(*resourcePodB.Cpu()) {
			// check for memory
			return resourcePodA.Memory().Cmp(*resourcePodB.Memory()) == 1
		}
		return resourcePodA.Cpu().Cmp(*resourcePodB.Cpu()) == 1
	})
	packs := map[uint64]*Packing{}
	var packings []*Packing
	var packing *Packing
	remainingPods := pods
	emptyPackables := PackablesFor(ctx, instanceTypes, constraints, pods, daemons)
	for len(remainingPods) > 0 {
		packables := []*Packable{}
		for _, packable := range emptyPackables {
			packables = append(packables, packable.DeepCopy())
		}
		if len(packables) == 0 {
			logging.FromContext(ctx).Errorf("Failed to find instance type option(s) for %v", apiobject.PodNamespacedNames(remainingPods))
			return packings, nil
		}
		packing, remainingPods = p.packWithLargestPod(remainingPods, packables)
		// checked all instance types and found no packing option
		if flattenedLen(packing.Pods...) == 0 {
			logging.FromContext(ctx).Errorf("Failed to compute packing, pod(s) %s did not fit in instance type option(s) %v", apiobject.PodNamespacedNames(remainingPods), packableNames(packables))
			remainingPods = remainingPods[1:]
			continue
		}
		key, err := hashstructure.Hash(packing, hashstructure.FormatV2, &hashstructure.HashOptions{SlicesAsSets: true})
		if err != nil {
			return nil, fmt.Errorf("hashing packings, %w", err)
		}
		if mainPack, ok := packs[key]; ok {
			mainPack.NodeQuantity++
			mainPack.Pods = append(mainPack.Pods, packing.Pods...)
			continue
		}
		packs[key] = packing
		packings = append(packings, packing)
	}
	for _, pack := range packings {
		logging.FromContext(ctx).Infof("Computed packing of %d node(s) for %d pod(s) with instance type option(s) %s", pack.NodeQuantity, flattenedLen(pack.Pods...), instanceTypeNames(pack.InstanceTypeOptions))
	}
	return packings, nil
}