Skip to content

Combining unstructured source with structured source for same resource can lead to templating errors #6593

Description

@marvin-roesch

What happened:
We are using the gateway-httproute source together with the unstructured source targeting HTTPRoute resources as well. The reason for this is that we want to generate additional records for some HTTPRoutes in a way that is not supported by the standard Gateway source. In particular, we're trying to create CNAME records for some routes under hostnames that are not matched by any of the listeners those routes are attached to.

When creating an HTTPRoute resource without .spec.hostnames specified (or empty), our FQDN template fails to evaluate with the following error:

template: endpoint:13:32: executing "endpoint" at <.Spec.hostnames>: can't evaluate field hostnames in type v1.HTTPRouteSpec

This is likely more generally a problem for any case where the unstructured source is combined with structured ones that work on the same resource kinds, especially if --combine-fqdn-annotation is provided as argument.

The root cause is that the same templates are used for structured and unstructured data, which have different underlying types. There are also no template functions to deal with this effectively.

What you expected to happen: Either the template should be successfully evaluated or not attempted to evaluate at all. We do not need it for the normal Gateway source, only for the unstructured one.

How to reproduce it (as minimally and precisely as possible):
Run external-dns with the following arguments:

--source=unstructured
--source=gateway-httproute
--unstructured-resource=httproutes.v1.gateway.networking.k8s.io
--fqdn-template="{{ range .Spec.hostnames }}{{ . }},{{ end }}"
--target-template="some-fixed-cname-target.example.com."

Then, apply the following HTTPRoute resource (needs some Gateway to be configured in the same namespace):

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: test
spec:
  parentRefs:
    - group: gateway.networking.k8s.io
      kind: Gateway
      namespace: example-gateway
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: example-service
          port: 80

external-dns will immediately log the above message for this resource.

Anything else we need to know?: We can work around this by using the --fqdn-target-template option in our case, but I don't think that's generally applicable.

As for a fix, I think the best course of action is to switch or at least allow for a wholly separate template to be specified for the unstructured source. The data passed in is fundamentally different from that for structured sources, so I think that's better in the long run. Alternatively, there should be additional information provided to the template to effectively distinguish structured from unstructured data. As a last resort, additional template functions that allow for e.g. type checks ("Is this value an unstructured map[string]any or some actual struct type?") would also help deal with this.

Environment:

  • External-DNS version (use external-dns --version): 0.21.0

Checklist

  • I have searched existing issues and tried to find a fix myself
  • I am using the latest release,
    or have checked the staging image to confirm the bug is still reproducible
  • I have provided the actual process flags (not Helm values)
  • I have provided kubectl get <resource> -o yaml output including status
  • I have provided full external-dns debug logs
  • I have described what DNS records exist and what I expected

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions