Skip to content

HTTPRoute rules helper drops zero weight and backendRef filters #613

Description

@aslafy-z

Follow-up to #603. While reviewing the HTTPRoute backendRef port fix, two pre-existing defects were confirmed in the same application.httpRoute.rules helper block. They are out of scope for the port PR and should be fixed once it is merged.

1. weight: 0 is silently dropped

The renderer guards weight with a truthiness check ({{- if .weight }}), so an explicit weight: 0 is omitted from the manifest. Per the Gateway API, an omitted weight defaults to 1, so a backend the operator drained with weight: 0 keeps receiving traffic.

Reproduce:

httpRoute:
  enabled: true
  parentRefs:
    - name: my-gateway
  hostnames:
    - example.com
  rules:
    - backendRefs:
        - name: blue
          port: 80
          weight: 0
        - name: green
          port: 80
          weight: 100

Rendered output contains no weight field on blue. Fix with a presence check ({{- if not (kindIs "invalid" .weight) }}), the same idiom #603 uses for port.

Related: .weight | int silently coerces non-integer values (e.g. "10%") to 0 and the Gateway API range 0..1000000 is not validated. Applying the same validate-then-render pattern used for port would fail loudly instead.

2. Per-backendRef filters are silently discarded

The backendRef renderer is a field whitelist (name, port, weight, namespace, kind, group), so the HTTPBackendRef.filters field passes values.schema.json, renders successfully, and never reaches the cluster:

rules:
  - backendRefs:
      - name: example-service
        port: 80
        filters:
          - type: RequestHeaderModifier
            requestHeaderModifier:
              add:
                - name: x-canary
                  value: "true"

The rendered backendRef contains only name and port. Either add a filters passthrough (filters: {{ .filters | toYaml | nindent 6 }}) or render the whole ref via toYaml with coerced port/weight so future spec fields pass through as well. Rule-level matches/filters/timeouts already use the toYaml passthrough pattern.

Both behaviors were confirmed with live helm template renders against the chart.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions