func createRouteStatus()

in pkg/ingress/kube/gateway/istio/conditions.go [45:173]


func createRouteStatus(parentResults []RouteParentResult, obj config.Config, currentParents []k8s.RouteParentStatus) []k8s.RouteParentStatus {
	parents := make([]k8s.RouteParentStatus, 0, len(parentResults))
	// Fill in all the gateways that are already present but not owned by us. This is non-trivial as there may be multiple
	// gateway controllers that are exposing their status on the same route. We need to attempt to manage ours properly (including
	// removing gateway references when they are removed), without mangling other Controller's status.
	for _, r := range currentParents {
		if r.ControllerName != constants.ManagedGatewayController {
			// We don't own this status, so keep it around
			parents = append(parents, r)
		}
	}
	// Collect all of our unique parent references. There may be multiple when we have a route without section name,
	// but reference a parent with multiple sections.
	// While we process these internally for-each sectionName, in the status we are just supposed to report one merged entry
	seen := map[k8s.ParentReference][]RouteParentResult{}
	seenReasons := sets.New[ParentErrorReason]()
	successCount := map[k8s.ParentReference]int{}
	for _, incoming := range parentResults {
		// We will append it if it is our first occurrence, or the existing one has an error. This means
		// if *any* section has no errors, we will declare Admitted
		if incoming.DeniedReason == nil {
			successCount[incoming.OriginalReference]++
		}
		seen[incoming.OriginalReference] = append(seen[incoming.OriginalReference], incoming)
		if incoming.DeniedReason != nil {
			seenReasons.Insert(incoming.DeniedReason.Reason)
		} else {
			seenReasons.Insert(ParentNoError)
		}
	}
	reasonRanking := []ParentErrorReason{
		// No errors is preferred
		ParentNoError,
		// All route level errors
		ParentErrorNotAllowed,
		ParentErrorNoHostname,
		ParentErrorParentRefConflict,
		// Failures to match the Port or SectionName. These are last so that if we bind to 1 listener we
		// just report errors for that 1 listener instead of for all sections we didn't bind to
		ParentErrorNotAccepted,
	}
	// Next we want to collapse these. We need to report 1 type of error, or none.
	report := map[k8s.ParentReference]RouteParentResult{}
	for _, wantReason := range reasonRanking {
		if !seenReasons.Contains(wantReason) {
			continue
		}
		// We found our highest priority ranking, now we need to collapse this into a single message
		for k, refs := range seen {
			for _, ref := range refs {
				reason := ParentNoError
				if ref.DeniedReason != nil {
					reason = ref.DeniedReason.Reason
				}
				if wantReason != reason {
					// Skip this one, it is for a less relevant reason
					continue
				}
				exist, f := report[k]
				if f {
					if ref.DeniedReason != nil {
						if exist.DeniedReason != nil {
							// join the error
							exist.DeniedReason.Message += "; " + ref.DeniedReason.Message
						} else {
							exist.DeniedReason = ref.DeniedReason
						}
					}
				} else {
					exist = ref
				}
				report[k] = exist
			}
		}
		// Once we find the best reason, do not consider any others
		break
	}

	// Now we fill in all the parents we do own
	for k, gw := range report {
		msg := "Route was valid"
		if successCount[k] > 1 {
			msg = fmt.Sprintf("Route was valid, bound to %d parents", successCount[k])
		}
		conds := map[string]*condition{
			string(k8s.RouteConditionAccepted): {
				reason:  string(k8s.RouteReasonAccepted),
				message: msg,
			},
			string(k8s.RouteConditionResolvedRefs): {
				reason:  string(k8s.RouteReasonResolvedRefs),
				message: "All references resolved",
			},
		}
		if gw.RouteError != nil {
			// Currently, the spec is not clear on where errors should be reported. The provided resources are:
			// * Accepted - used to describe errors binding to parents
			// * ResolvedRefs - used to describe errors about binding to objects
			// But no general errors
			// For now, we will treat all general route errors as "Ref" errors.
			conds[string(k8s.RouteConditionResolvedRefs)].error = gw.RouteError
		}
		if gw.DeniedReason != nil {
			conds[string(k8s.RouteConditionAccepted)].error = &ConfigError{
				Reason:  ConfigErrorReason(gw.DeniedReason.Reason),
				Message: gw.DeniedReason.Message,
			}
		}

		var currentConditions []metav1.Condition
		currentStatus := slices.FindFunc(currentParents, func(s k8sbeta.RouteParentStatus) bool {
			return parentRefString(s.ParentRef) == parentRefString(gw.OriginalReference)
		})
		if currentStatus != nil {
			currentConditions = currentStatus.Conditions
		}
		parents = append(parents, k8s.RouteParentStatus{
			ParentRef:      gw.OriginalReference,
			ControllerName: constants.ManagedGatewayController,
			Conditions:     setConditions(obj.Generation, currentConditions, conds),
		})
	}
	// Ensure output is deterministic.
	// TODO: will we fight over other controllers doing similar (but not identical) ordering?
	sort.SliceStable(parents, func(i, j int) bool {
		return parentRefString(parents[i].ParentRef) > parentRefString(parents[j].ParentRef)
	})
	return parents
}