<a id="explanation-gateway-route"></a>

# How gateway-route works

The `gateway-route` interface is used together with the
[`gateway-api-integrator`](https://charmhub.io/gateway-api-integrator) charm,
which manages a Kubernetes [Gateway API](https://gateway-api.sigs.k8s.io/)
`Gateway` resource. The Ingress Configurator charm connects a workload that
requires an `ingress` relation to the `Gateway` resource, while also exposing
configuration options - such as `hostname` and `paths` - that can be tuned
without modifying either the workload or the `gateway-api-integrator` charm.

#### NOTE
The Gateway API is a Kubernetes-native concept, so the `gateway-route`
relation should only be used on a Kubernetes substrate. The charm must also be
deployed with `--trust` so it can manage Kubernetes resources.

## Architecture

How the backend `Service` is reached depends on whether the workload has
opened its port in Juju (see [Backend service selection](#explanation-backend-service-selection)).

In the diagrams below, green arrows represent references between Kubernetes
resources (traffic/data flow) and blue dashed arrows represent Juju relations.
Charm units are shown as rounded nodes, while Kubernetes resources are shown
as rectangular nodes.

### Port open

### Port closed

## How HTTPRoute resources are created

The Ingress Configurator builds `HTTPRoute` resources based on the
`https_mode` received from the provider (see
[The gateway-route relation](https://canonical.com/juju/docs/ingress-configurator-charm/latest/reference/gateway-route/index.html.md#reference-gateway-route)) and the
hostname(s) from its own configuration:

- **One HTTP route** is always created. It covers all hostnames and attaches
  to every per-hostname HTTP listener on the `Gateway` via multiple
  `parentRefs`. When no hostnames are configured, it falls back to the
  `Gateway`’s hostname-less HTTP listener.
- When `https_mode` is `enabled` or `enforced`, **one HTTPS route per
  hostname** is created, each attaching to its corresponding per-hostname HTTPS
  listener.
- When `https_mode` is `enforced`, the HTTP route does **not** forward to
  the backend. Instead it issues a `301` HTTPS redirect using a
  `RequestRedirect` filter.

<a id="explanation-backend-service-selection"></a>

## Backend service selection

The `HTTPRoute` forwards traffic to a Kubernetes `Service`. Which `Service` is
used depends on whether the workload charm has opened its port in Juju:

- **Port is open**: the workload’s own `Service` is referenced directly by the
  `HTTPRoute`’s `backendRefs`.
- **Port is closed**: the Ingress Configurator creates a selector-based
  `Service` that targets the workload’s pods by the
  `app.kubernetes.io/name` label. This allows routing even when the workload
  has not declared its port to Juju.

All resources created by the Ingress Configurator are labelled with
`ingress-configurator.charm.juju.is/managed-by` so they can be discovered and
cleaned up on relation departure.

## Constraints and limitations

- **Kubernetes only**: The Gateway API is a Kubernetes-native concept, so the
  `gateway-route` relation should only be used on a Kubernetes substrate.
- **HTTP backend protocol only**: The `backend-protocol` configuration option
  only accepts `http` with `gateway-route`. TLS termination happens at the
  `Gateway`, not at the backend.
- **One route relation at a time**: The charm blocks if more than one of
  `haproxy-route`, `haproxy-route-tcp`, or `gateway-route` is related
  simultaneously.
- **One `gateway-route` relation per ingress-configurator**: A single
  `gateway-api-integrator` can accept multiple `gateway-route` relations, but
  each `ingress-configurator` instance is limited to one `gateway-route`
  relation. To route traffic for multiple workloads through the same `Gateway`,
  deploy a separate `ingress-configurator` for each workload and relate them
  all to the same `gateway-api-integrator`.
- **`--trust` required**: The charm needs Kubernetes RBAC permissions to
  manage `HTTPRoute` and `Service` resources.
- **Same model only**: The workload and the Ingress Configurator must run in
  the same Juju model (Kubernetes namespace); cross-model relations are not
  supported. When the workload’s port is closed, the selector-based `Service`
  only matches pods in its own namespace. When the port is open, the
  `HTTPRoute`’s `backendRef` resolves to the `HTTPRoute`’s own namespace (a
  cross-namespace reference would require a `ReferenceGrant`, which the charm
  does not create).
