# Route delegation status draft ## Design In this doc, I will call a HTTPRoute with a least one rule with a non-`nil` `allowedRoutes` field a "parent" HTTPRoute. - If a route references another route in its `parentRef` field, and has an `allowedRoute` in one of its route rules, it is a *parent* Route. The basic design: - we'll add a `inclusions` stanza inside the parents stanza in status, which will contain details about the route being a parent, successfully or not. - the `inclusions` stanza will only be populated if a rule has a non-nil `allowedRoutes` section. - once the `inclusions` stanza is populated, `supportedKinds` and `attachedRoutes` fields must be filled in, in addition to the mandatory Conditions. Here's what the proposal looks like for an attached child route: ```yaml status: # Existing stanza is the same parents: - parentref: name: somegateway namespace: somenamespace controllerName: controller.io/somecontroller conditions: - <conditions here> inclusions: - supportedKinds: - kind: HTTPRoute attachedRoutes: 1 conditions: - <conditions here> ``` We add a new `inclusions` stanza inside the the top-level `parents` status. This stanza will be `+optional` and `omitempty`, with the following rules: - `children` will be nil in all non-parent HTTPRoutes. - Once a HTTPRoute is a parent, then this stanza must also be non-nil. We need to add this inside the parents stanza because it's possible that a parent HTTPRoute may be attached to more than one parent (probably Gateways) of its own, and there may be different status between different Gateways. For example, if a parent HTTPRoute is attached to two Gateways, one of which has a wildcard hostname, whether or not the child HTTPRoute attempting to attach to the parent HTTPRoute will be accepted is dependent on the hostname setting on the Gateway Listener. See the example below for an attempt;**this may need reworking**. The struct itself is the same struct as the Gateway Listener status. We probably will be able to reuse the same struct, at least to begin with. Conditions are required regardless, and we keep the `supportedKinds` and `attachedRoutes` as useful info the same as the Listener. - `supportedKinds` and `attachedRoutes` must be filled in by a controller that reconciles a parent HTTPRoute. That is: - `supportedKinds` must be filled in with a list of the kinds that can be attached to this parent. (This may be redundant if we're mandating that routes can only include the same Kind). - `attachedRoutes` should show the number of routes that have _successfully_ attached to this parent. For Conditions: - when the controller first sees the parent Route, it must add the following Condition Types: - `Attached`: one or more Routes have successfully attached to this parent. False if zero Routes have attached successfully. - `Conflicted`: one or more settings in the parent conflict with settings in one of the child routes. The message should contain more details. Routes that cause this to be true do not attach. - `ResolvedRefs`: one or more Routes have failed to attach because there is a problem with their reference. (for example, they could not be found). Those routes do not attach. - `NotSupported`: the controller that is reconciling this Route does not support attaching at least one of the routes that has attempted to attach, or the parent route is already a child route itself. Those routes do not attach. ## Example Here's an example, only including status for the HTTPRoutes: ```yaml --- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: name: gateway-a spec: gatewayClassName: acme-lb listeners: - name: http protocol: HTTP port: 80 hostname: *.example.com --- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: Gateway metadata: name: gateway-b spec: gatewayClassName: acme-lb listeners: # Use GatewayClass defaults for listener definition. - name: http protocol: HTTP port: 80 hostname: subdomain.example.com --- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: name: http-parent spec: parentRefs: - name: gateway-a sectionName: http - name: gateway-b sectionName: http rules: - allowedRoutes: kinds: - kind: HTTPRoute namespaces: from: Same - backendRefs: - name: default-svc port: 8080 status: parents: - controllerName: somevalue parentRef: name: gateway-a conditions: - type: Accepted status: true reason: Accepted message: Successfully accepted - controllerName: somevalue parentRef: name: gateway-b conditions: - type: Attached status: false reason: HostnameMismatch message: The route could not be attached because of a hostname mismatch in a child route. --- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: HTTPRoute metadata: name: http-child spec: parentRefs: - name: gateway-a sectionName: http hostnames: - testdomain.example.com rules: - backendRefs: - name: foo-svc port: 8080 ``` > youngnick note: Uh-oh, this example is valid according to what I see as the rules, but there's no way to represent it without reworking the status completely. > > This will need a child route to have a parentRefs namespaced by its *inclusion path* rather than by its direct parent. I'm going to need to think about this some more. In this example, the HTTPRoute `http-parent` is able to attach to either Gateway by itself, but once the child is included, `gateway-a` will accept it, and `gateway-b` will not, since the hostnames don't match. This is a slightly contrived example, but serves to illustrate that we need a way for both `http-parent` and `http-child` to indicate that something has gone wrong.