func ApplyContainerResourceCustomization()

in operator/pkg/controllers/utils.go [197:266]


func ApplyContainerResourceCustomization(isNamespaced bool, m *manifest.Objects, controllerName string, controllerGVK schema.GroupVersionKind, containers []customizev1beta1.ContainerResourceSpec, replicas *int64) error {
	if err := checkForDuplicateContainers(containers); err != nil {
		return err
	}
	cMap := make(map[string]customizev1beta1.ResourceRequirements, len(containers)) // cMap is a map of container name to its corresponding resource customization.
	cMapApplied := make(map[string]bool)                                            // cMapApplied is a map of container name to a boolean indicating whether the customization for this container is applied.
	for _, c := range containers {
		cMap[c.Name] = c.Resources
		cMapApplied[c.Name] = false
	}
	var shouldUpdateHPA bool // shouldUpdateHPA is a boolean indicating if we need to update the "minReplicas" field in the HorizontalPodAutoscaler for webhook manager
	// apply customization to the matching controller in the manifest
	for _, item := range m.Items {
		if item.GroupVersionKind() == controllerGVK { // match GVK
			if (!isNamespaced && item.GetName() == controllerName) || // match exact controller name for cluster-scoped controller
				(isNamespaced && strings.HasPrefix(item.GetName(), controllerName)) { // match the prefix for namespace-scoped controller, ignore the namespace ID suffix
				// apply container resource customization for this controller.
				if err := item.MutateContainers(customizeContainerResourcesFn(cMap, cMapApplied)); err != nil {
					return err
				}
				// apply replicas customization for this controller.
				if replicas != nil && controllerName == "cnrm-webhook-manager" { // currently only support customizing replicas for cnrm-webhook-manager.
					if err := item.SetNestedField(*replicas, "spec", "replicas"); err != nil {
						return err
					}
					shouldUpdateHPA = true
				}
				break // we already found the matching controller, no need to keep looking.
			}
		}
	}
	// if we update replicas for webhook manager deployment, we need to adjust its HPA as well.
	if shouldUpdateHPA {
		HPAGVK := schema.GroupVersionKind{
			Group:   autoscalingv1.SchemeGroupVersion.Group,
			Version: autoscalingv1.SchemeGroupVersion.Version,
			Kind:    "HorizontalPodAutoscaler",
		}
		for _, item := range m.Items {
			if item.GroupVersionKind() == HPAGVK && item.GetName() == "cnrm-webhook" {
				// update "minReplicas".
				if err := item.SetNestedField(*replicas, "spec", "minReplicas"); err != nil {
					return err
				}
				// update "maxReplicas" to match "minReplicas" if it is smaller than "minReplicas".
				maxReplicas, found, err := unstructured.NestedInt64(item.UnstructuredObject().Object, "spec", "maxReplicas")
				if err != nil {
					return err
				}
				if found && (maxReplicas < *replicas) {
					if err := item.SetNestedField(*replicas, "spec", "maxReplicas"); err != nil {
						return err
					}
				}
				break // we already found the HPA, no need to keep looking.
			}
		}
	}
	// check if all container resource customizations are applied
	var notApplied []string
	for c, applied := range cMapApplied {
		if !applied {
			notApplied = append(notApplied, c)
		}
	}
	if len(notApplied) > 0 {
		return fmt.Errorf("resource customization failed for the following containers because there are no matching containers in the manifest: %s", strings.Join(notApplied, ", "))
	}
	return nil
}