The route hostname policy names one API version for TLSRoute, and it is the version scheduled to go away.
# packages/system/cozystack-basics/templates/route-hostname-policy.yaml
:60 apiVersions: ["v1", "v1beta1"] resources: ["httproutes"]
:94 apiVersions: ["v1alpha2"] resources: ["tlsroutes"]
The HTTPRoute rule names both served versions and neither is deprecated, so that half is fine. The TLSRoute rule names only v1alpha2, while the bundle this repository ships (packages/system/gateway-api-crds, bundle-version: v1.5.1) serves tlsroutes at v1 (storage), v1alpha2 and v1alpha3, with both alpha versions marked deprecated.
Nothing is broken today. matchConstraints.matchPolicy defaults to Equivalent (go doc k8s.io/api/admissionregistration/v1.MatchResources), so a request arriving at v1 is converted to the named version and the rule matches. Coverage is complete while v1alpha2 is still served.
What happens when a bundle drops it is the reason to file this now. The rule would then name no served version at all. A request at v1 matches no rule, the policy does not run, and failurePolicy: Fail does not help, because there is no failure to fail on — only an absence of match. Nothing appears in logs, the policy's status stays healthy, and the loss surfaces only when somebody publishes a TLSRoute outside the tenant apex and it goes through.
The fix is to name all three: apiVersions: ["v1", "v1alpha2", "v1alpha3"], plus the corresponding pin in packages/system/cozystack-basics/tests/route-hostname-policy_test.yaml. It is close to free today, but the schemas are not identical and the difference is worth knowing. Loading the bundle and comparing spec.versions[].schema.openAPIV3Schema.properties.spec.properties.hostnames gives:
tlsroutes v1 minItems: 1, three x-kubernetes-validations (no IP, RFC-1123, wildcard first label)
tlsroutes v1alpha2 no minItems, no validations
tlsroutes v1alpha3 identical to v1
The field is an array of strings in all three, so the policy's CEL sees the same shape and the expression needs no change. What differs is how much the CRD itself already enforces: at v1 an empty hostnames is rejected by the schema, at v1alpha2 it is not. That is worth noting because it means the policy is doing strictly more work on the alpha version than on v1, not the same work. Better done before the bundle bump rather than as part of it.
What is measured and what is not
Measured directly: the two apiVersions lines above, read from main.
Measured directly as well, after the first version of this text went up: the per-version served/storage/deprecated flags, and the per-version hostnames schemas, both by loading the bundle with a YAML parser rather than scanning it. The earlier claim that the three schemas are identical came from review notes and turned out to be wrong in the detail above.
Not established at all: the apiserver's behaviour once no named version is served. That follows from the semantics of Equivalent rather than from a cluster where v1alpha2 has been removed. If this needs to be beyond argument before anyone acts on it, the experiment is small — a kind cluster with a bundle that disables v1alpha2, then a TLSRoute at v1 with a hostname outside the apex, and see whether it is admitted.
Pre-existing, and not introduced by any open PR: apiVersions: ["v1alpha2"] is unchanged on main and on the branches currently in flight.
The route hostname policy names one API version for TLSRoute, and it is the version scheduled to go away.
The HTTPRoute rule names both served versions and neither is deprecated, so that half is fine. The TLSRoute rule names only
v1alpha2, while the bundle this repository ships (packages/system/gateway-api-crds,bundle-version: v1.5.1) servestlsroutesatv1(storage),v1alpha2andv1alpha3, with both alpha versions marked deprecated.Nothing is broken today.
matchConstraints.matchPolicydefaults toEquivalent(go doc k8s.io/api/admissionregistration/v1.MatchResources), so a request arriving atv1is converted to the named version and the rule matches. Coverage is complete whilev1alpha2is still served.What happens when a bundle drops it is the reason to file this now. The rule would then name no served version at all. A request at
v1matches no rule, the policy does not run, andfailurePolicy: Faildoes not help, because there is no failure to fail on — only an absence of match. Nothing appears in logs, the policy's status stays healthy, and the loss surfaces only when somebody publishes a TLSRoute outside the tenant apex and it goes through.The fix is to name all three:
apiVersions: ["v1", "v1alpha2", "v1alpha3"], plus the corresponding pin inpackages/system/cozystack-basics/tests/route-hostname-policy_test.yaml. It is close to free today, but the schemas are not identical and the difference is worth knowing. Loading the bundle and comparingspec.versions[].schema.openAPIV3Schema.properties.spec.properties.hostnamesgives:The field is an array of strings in all three, so the policy's CEL sees the same shape and the expression needs no change. What differs is how much the CRD itself already enforces: at
v1an emptyhostnamesis rejected by the schema, atv1alpha2it is not. That is worth noting because it means the policy is doing strictly more work on the alpha version than onv1, not the same work. Better done before the bundle bump rather than as part of it.What is measured and what is not
Measured directly: the two
apiVersionslines above, read frommain.Measured directly as well, after the first version of this text went up: the per-version served/storage/deprecated flags, and the per-version
hostnamesschemas, both by loading the bundle with a YAML parser rather than scanning it. The earlier claim that the three schemas are identical came from review notes and turned out to be wrong in the detail above.Not established at all: the apiserver's behaviour once no named version is served. That follows from the semantics of
Equivalentrather than from a cluster wherev1alpha2has been removed. If this needs to be beyond argument before anyone acts on it, the experiment is small — a kind cluster with a bundle that disablesv1alpha2, then a TLSRoute atv1with a hostname outside the apex, and see whether it is admitted.Pre-existing, and not introduced by any open PR:
apiVersions: ["v1alpha2"]is unchanged onmainand on the branches currently in flight.