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
What happened:
We are using the
gateway-httproutesource together with theunstructuredsource targetingHTTPRouteresources 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
HTTPRouteresource without.spec.hostnamesspecified (or empty), our FQDN template fails to evaluate with the following error: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-annotationis 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:
Then, apply the following
HTTPRouteresource (needs some Gateway to be configured in the same namespace):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-templateoption 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]anyor some actual struct type?") would also help deal with this.Environment:
external-dns --version): 0.21.0Checklist
or have checked the staging image to confirm the bug is still reproducible
kubectl get <resource> -o yamloutput includingstatus