add status message when attempting to attach to headless service (#12918)

If the `parent_ref` of an HTTPRoute resource is set to a headless service, the policy controller gives the HTTPRoute a status of NoMatchingParent:

```
  - conditions:
    - lastTransitionTime: "2024-07-30T22:52:24Z"
      message: ""
      reason: NoMatchingParent
      status: "False"
      type: Accepted
```

However, this can be misleading because the parent does exist, but is not a valid parent because it does not have a cluster IP.

We make this error easier to understand by adding a message to the status condition in this case:

```
    - lastTransitionTime: "2024-07-30T22:51:29Z"
      message: parent service must have a ClusterIP
      reason: NoMatchingParent
      status: "False"
      type: Accepted
```

Signed-off-by: Alex Leong <alex@buoyant.io>
This commit is contained in:
Alex Leong 2024-08-02 10:54:57 -07:00 committed by GitHub
parent 7bccd05de5
commit aa3e7d87f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 17 deletions

View File

@ -397,24 +397,22 @@ impl Index {
}
routes::ParentReference::Service(service, port) => {
// service is a valid parent if it exists and it has a cluster_ip.
let condition = if self
.services
.get(service)
.map_or(false, |svc| svc.valid_parent_service())
{
// If this route is an HTTPRoute and there exists a GRPCRoute
// with the same parent, the HTTPRoute should not be accepted
// because it is less specific.
// https://gateway-api.sigs.k8s.io/geps/gep-1426/#route-types
if id.gkn.kind == k8s_gateway_api::HttpRoute::kind(&())
&& self.parent_has_grpcroute_children(parent_ref)
{
route_conflicted()
} else {
accepted()
let condition = match self.services.get(service) {
Some(svc) if svc.valid_parent_service() => {
// If this route is an HTTPRoute and there exists a GRPCRoute
// with the same parent, the HTTPRoute should not be accepted
// because it is less specific.
// https://gateway-api.sigs.k8s.io/geps/gep-1426/#route-types
if id.gkn.kind == k8s_gateway_api::HttpRoute::kind(&())
&& self.parent_has_grpcroute_children(parent_ref)
{
route_conflicted()
} else {
accepted()
}
}
} else {
no_matching_parent()
Some(_svc) => headless_parent(),
None => no_matching_parent(),
};
Some(k8s_gateway_api::RouteParentStatus {
@ -861,6 +859,17 @@ fn no_matching_parent() -> k8s_core_api::Condition {
}
}
fn headless_parent() -> k8s_core_api::Condition {
k8s_core_api::Condition {
last_transition_time: k8s_core_api::Time(now()),
message: "parent service must have a ClusterIP".to_string(),
observed_generation: None,
reason: reasons::NO_MATCHING_PARENT.to_string(),
status: cond_statuses::STATUS_FALSE.to_string(),
type_: conditions::ACCEPTED.to_string(),
}
}
fn route_conflicted() -> k8s_core_api::Condition {
k8s_core_api::Condition {
last_transition_time: k8s_core_api::Time(now()),